diff --git a/cmd/kcp/kcp.go b/cmd/kcp/kcp.go index 5ba1c341980..c78407fc6ab 100644 --- a/cmd/kcp/kcp.go +++ b/cmd/kcp/kcp.go @@ -81,7 +81,7 @@ func main() { additionalMappingsFile = os.Args[i+1] } // else let normal flag processing fail } else if strings.HasPrefix(f, "--miniproxy-mapping-file") { - additionalMappingsFile = strings.TrimPrefix(f, "--mapping-file=") + additionalMappingsFile = strings.TrimPrefix(f, "--miniproxy-mapping-file=") } } diff --git a/contrib/mounts-virtualworkspace/Makefile b/contrib/mounts-virtualworkspace/Makefile new file mode 100644 index 00000000000..09c1ba78c5a --- /dev/null +++ b/contrib/mounts-virtualworkspace/Makefile @@ -0,0 +1,86 @@ + +GO_INSTALL = ./hack/go-install.sh + +TOOLS_DIR=hack/tools +TOOLS_GOBIN_DIR := $(abspath $(TOOLS_DIR)) +GOBIN_DIR=$(abspath ./bin) +PATH := $(GOBIN_DIR):$(TOOLS_GOBIN_DIR):$(PATH) +TMPDIR := $(shell mktemp -d) +KIND_CLUSTER_NAME ?= kind + +CONTROLLER_GEN_VER := v0.16.1 +CONTROLLER_GEN_BIN := controller-gen +CONTROLLER_GEN := $(TOOLS_DIR)/$(CONTROLLER_GEN_BIN)-$(CONTROLLER_GEN_VER) +export CONTROLLER_GEN # so hack scripts can use it + + +CODE_GENERATOR_VER := v2.1.0 +CODE_GENERATOR_BIN := code-generator +CODE_GENERATOR := $(TOOLS_GOBIN_DIR)/$(CODE_GENERATOR_BIN)-$(CODE_GENERATOR_VER) +export CODE_GENERATOR # so hack scripts can use it + +KCP_APIGEN_VER := v0.26.0 +KCP_APIGEN_BIN := apigen +KCP_APIGEN_GEN := $(TOOLS_DIR)/$(KCP_APIGEN_BIN)-$(KCP_APIGEN_VER) +export KCP_APIGEN_GEN # so hack scripts can use it + +OPENSHIFT_GOIMPORTS_VER := c72f1dc2e3aacfa00aece3391d938c9bc734e791 +OPENSHIFT_GOIMPORTS_BIN := openshift-goimports +OPENSHIFT_GOIMPORTS := $(TOOLS_DIR)/$(OPENSHIFT_GOIMPORTS_BIN)-$(OPENSHIFT_GOIMPORTS_VER) +export OPENSHIFT_GOIMPORTS # so hack scripts can use it + +VERSION ?= $(shell git describe --tags --always --dirty) + +LDFLAGS= -s -w \ + -extldflags '-static' + +all: build +.PHONY: all + +ldflags: + @echo $(LDFLAGS) + +tools: $(CONTROLLER_GEN) $(KCP_APIGEN_GEN) $ $(CODE_GENERATOR) $(OPENSHIFT_GOIMPORTS) ## Install tools +.PHONY: tools + +$(CONTROLLER_GEN): + GOBIN=$(TOOLS_GOBIN_DIR) $(GO_INSTALL) sigs.k8s.io/controller-tools/cmd/controller-gen $(CONTROLLER_GEN_BIN) $(CONTROLLER_GEN_VER) + +$(CODE_GENERATOR): + GOBIN=$(TOOLS_GOBIN_DIR) $(GO_INSTALL) github.com/kcp-dev/code-generator/v2 $(CODE_GENERATOR_BIN) $(CODE_GENERATOR_VER) + +$(KCP_APIGEN_GEN): + GOBIN=$(TOOLS_GOBIN_DIR) $(GO_INSTALL) github.com/kcp-dev/kcp/sdk/cmd/apigen $(KCP_APIGEN_BIN) $(KCP_APIGEN_VER) + +$(OPENSHIFT_GOIMPORTS): + GOBIN=$(TOOLS_GOBIN_DIR) $(GO_INSTALL) github.com/openshift-eng/openshift-goimports $(OPENSHIFT_GOIMPORTS_BIN) $(OPENSHIFT_GOIMPORTS_VER) + +.PHONY: require-% +require-%: + @if ! command -v $* 1> /dev/null 2>&1; then echo "$* not found in ${PATH}"; exit 1; fi + +.PHONY: verify-go-versions +verify-go-versions: ## Verify go versions + hack/verify-go-versions.sh + +build: WHAT ?= ./cmd/... +build: require-jq require-go require-git verify-go-versions ## Build the project + GOOS=$(OS) GOARCH=$(ARCH) CGO_ENABLED=0 go build $(BUILDFLAGS) -ldflags="$(LDFLAGS)" -o bin $(WHAT) +.PHONY: build + +crds: $(CONTROLLER_GEN) $(YAML_PATCH) ## Generate crds + ./hack/update-codegen-crds.sh +.PHONY: crds + +codegen: crds $(CODE_GENERATOR) ## Generate all + go mod download + ./hack/update-codegen-clients.sh + $(MAKE) imports + +.PHONY: imports +imports: $(OPENSHIFT_GOIMPORTS) verify-go-versions + $(OPENSHIFT_GOIMPORTS) -m github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace + +test: + go test ./... + diff --git a/contrib/mounts-virtualworkspace/README.md b/contrib/mounts-virtualworkspace/README.md new file mode 100644 index 00000000000..eff93aa1b12 --- /dev/null +++ b/contrib/mounts-virtualworkspace/README.md @@ -0,0 +1,149 @@ +# Remote mounts virtual workspace example + +This is an example of how to use the mounts feature in kcp to mount a target cluster into a workspace. +Mount happens at front-proxy level via reverse proxy. You need to implement your own VirtualWorkspace to handle this. +and this example shows how to do it. + +## This is example codebase, and should be used only as example. + +# Step by step guide + +Step by step guide how to setup this example. + +1. Start kcp with mounts feature gate enabled: + +``` +go run ./cmd/kcp start --miniproxy-mapping-file=./contrib/mounts-virtualworkspace/assets/path-mapping.yaml --feature-gates=WorkspaceMounts=true +``` + +2. Setup all required workspaces and exports for virtual workspace to run: + +Provider workspace where all the target cluster will be defined with secrets. +These clusters can be mounted later on by the any workspace. + +Setup providers: + +``` +cd ./contrib/mounts-virtualworkspace/ + +# Set kcp KUBECONFIG +export KUBECONFIG=../../.kcp/admin.kubeconfig + +kubectl ws use :root +# create provider workspaces +kubectl ws create providers --enter +kubectl ws create mounts --enter + +# create exports +kubectl create -f config/mounts/resources/apiresourceschema-targetkubeclusters.targets.contrib.kcp.io.yaml +kubectl create -f config/mounts/resources/apiresourceschema-kubeclusters.mounts.contrib.kcp.io.yaml +kubectl create -f config/mounts/resources/apiresourceschema-targetvclusters.targets.contrib.kcp.io.yaml +kubectl create -f config/mounts/resources/apiresourceschema-vclusters.mounts.contrib.kcp.io.yaml +kubectl create -f config/mounts/resources/apiexport-mounts.contrib.kcp.io.yaml +kubectl create -f config/mounts/resources/apiexport-targets.contrib.kcp.io.yaml + +``` + +3. Start virtual workspace process: +``` + go run ./cmd/virtual-workspaces/ start \ + --kubeconfig=../../.kcp/admin.kubeconfig \ + --tls-cert-file=../../.kcp/apiserver.crt \ + --tls-private-key-file=../../.kcp/apiserver.key \ + --authentication-kubeconfig=../../.kcp/admin.kubeconfig \ + --virtual-workspaces-proxy-hostname=https://localhost:6444 \ + -v=8 +``` + +4. Continue bootstrapping the mounts example: + +``` +# create operators namespace where platforms operators will create objects. This could be many of them. +# for this example we will use only one. + +kubectl ws use :root +kubectl ws create operators --enter +kubectl ws create mounts --enter + +# bind the exports +# see https://github.com/kcp-dev/kcp/issues/3189 +kubectl create -f config/mounts/resources/apibinding-targets.yaml + +# Create a target cluster to `kind` cluster locally: + +# create kind cluster if not already created +kind create cluster --name kind --kubeconfig kind.kubeconfig + +#create secret with kubeconfig: +kubectl ws use root:operators:mounts +kubectl create secret generic kind-kubeconfig --from-file=kubeconfig=kind.kubeconfig + +# create target cluster: +kubectl create -f config/mounts/resources/example-target-cluster.yaml + +# create vcluster target: +kubectl create -f config/mounts/resources/example-target-vcluster.yaml + +# get secret string: +kubectl get TargetKubeCluster proxy-cluster -o jsonpath='{.status.secretString}' +HS7kd992rQNedzcY + + cluster: YJfI5DIEoQ0ySamJ + +# Create a consumer workspace for mounts: +kubectl ws use :root +kubectl ws create consumer --enter +kubectl ws create kind-cluster + +kubectl create -f config/mounts/resources/apibinding-mounts.yaml + +# !!!!! replace secrets string first in the file bellow : +kubectl create -f config/mounts/resources/example-mount-cluster.yaml + +# annotate the workspace with mount, putting the intent that this should be mounted: + kubectl annotate workspace kind-cluster experimental.tenancy.kcp.io/mount='{"spec":{"ref":{"kind":"KubeCluster","name":"proxy-cluster","apiVersion":"mounts.contrib.kcp.io/v1alpha1"}}}' +``` + +5. Check the mounts reconciler logs: + +Now workspace should be backed by mountpoint from front-proxy: + +``` +kubectl ws use kind-cluster +k get pods -A +NAMESPACE NAME READY STATUS RESTARTS AGE +kube-system coredns-7db6d8ff4d-4l625 1/1 Running 0 22h +kube-system coredns-7db6d8ff4d-ntf95 1/1 Running 0 22h +kube-system etcd-kind-control-plane 1/1 Running 0 22h +kube-system kindnet-vv872 1/1 Running 0 22h +kube-system kube-apiserver-kind-control-plane 1/1 Running 0 22h +kube-system kube-controller-manager-kind-control-plane 1/1 Running 0 22h +kube-system kube-proxy-lkv29 1/1 Running 0 22h +kube-system kube-scheduler-kind-control-plane 1/1 Running 0 22h +local-path-storage local-path-provisioner-988d74bc-dqnd7 1/1 Running 0 22h +``` + +# Vclusters example + +vCluster are backed by vCluster mounts. This is a way to create a virtual cluster that is backed by a real cluster. +You can either provide a kubeconfig or a target cluster to back the vCluster or secretString for "target" in the system. + +kubectl ws create vcluster +kubectl create -f config/mounts/resources/example-mount-vcluster.yaml + +# annotate the workspace with mount, putting the intent that this should be mounted: + kubectl annotate workspace vcluster experimental.tenancy.kcp.io/mount='{"spec":{"ref":{"kind":"VCluster","name":"virtual-cluster","apiVersion":"mounts.contrib.kcp.io/v1alpha1"}}}' + + kubectl annotate workspace vcluster-3 experimental.tenancy.kcp.io/mount='{"spec":{"ref":{"kind":"VCluster","name":"virtual-cluster-3","apiVersion":"mounts.contrib.kcp.io/v1alpha1"}}}' + + +# Known issues + +1. `TargetKubeCluster` changes do not propagate to `KubeCluster` need to wire them up. +Challenge is that when these 2 objects are in separate bindings, its more machinery to make them work together. + +2. VirtualWorkspace is not yet fully shards aware. Ideally it should be 1 per each shard, and handle only its +own workspaces. + +3. KubeCluster changes not applied to Workspaces. This might be a bug in core. Need to validate. + diff --git a/contrib/mounts-virtualworkspace/apis/mounts/OWNERS b/contrib/mounts-virtualworkspace/apis/mounts/OWNERS new file mode 100644 index 00000000000..1b4da8bace9 --- /dev/null +++ b/contrib/mounts-virtualworkspace/apis/mounts/OWNERS @@ -0,0 +1,2 @@ +reviewers: +- mjudeikis diff --git a/contrib/mounts-virtualworkspace/apis/mounts/register.go b/contrib/mounts-virtualworkspace/apis/mounts/register.go new file mode 100644 index 00000000000..d1071d4750c --- /dev/null +++ b/contrib/mounts-virtualworkspace/apis/mounts/register.go @@ -0,0 +1,23 @@ +/* +Copyright 2023 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 mounts + +const ( + GroupName = "mounts.contrib.kcp.io" + KubeClusterKind = "KubeCluster" + VClusterKind = "VCluster" +) diff --git a/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1/doc.go b/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1/doc.go new file mode 100644 index 00000000000..9dd8c376a5e --- /dev/null +++ b/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2024 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. +*/ + +// +k8s:deepcopy-gen=package,register +// +groupName=mounts.contrib.kcp.io +// +k8s:openapi-gen=true +package v1alpha1 diff --git a/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1/register.go b/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1/register.go new file mode 100644 index 00000000000..a0336a86549 --- /dev/null +++ b/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1/register.go @@ -0,0 +1,55 @@ +/* +Copyright 2023 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 v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts" +) + +// SchemeGroupVersion is group version used to register these objects. +var SchemeGroupVersion = schema.GroupVersion{Group: mounts.GroupName, Version: "v1alpha1"} + +// Kind takes an unqualified kind and returns back a Group qualified GroupKind. +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource. +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &KubeCluster{}, + &KubeClusterList{}, + &VCluster{}, + &VClusterList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1/types.go b/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1/types.go new file mode 100644 index 00000000000..af7a5fccf29 --- /dev/null +++ b/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1/types.go @@ -0,0 +1,8 @@ +package v1alpha1 + +const ( + + // InternalWorkspaceProxyKeyLabel is an internal label set on a WorkspaceProxy resource that contains the full hash of the WorkspaceProxyKey, generated with the ToProxyTargetKey(..) + // helper func, this label is used for reverse lookups of workspaceProxyKey to WorkspaceProxy. + InternalWorkspaceProxyKeyLabel = "internal.mounts.contrib.kcp.io/key" +) diff --git a/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1/types_kubecluster.go b/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1/types_kubecluster.go new file mode 100644 index 00000000000..f6b17cb0dab --- /dev/null +++ b/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1/types_kubecluster.go @@ -0,0 +1,126 @@ +/* +Copyright 2023 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 v1alpha1 + +import ( + tenancyv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/tenancy/v1alpha1" + conditionsv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// KubeCluster describes the current KubeCluster proxy object. +// +// +crd +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster,categories=contrib +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=`.status.conditions[?(@.type=="ClusterReady")].status` +// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=`.status.phase` +type KubeCluster struct { + v1.TypeMeta `json:",inline"` + // +optional + v1.ObjectMeta `json:"metadata,omitempty"` + // +optional + Spec KubeClusterSpec `json:"spec,omitempty"` + // +optional + Status KubeClusterStatus `json:"status,omitempty"` +} + +// KubeClusterSpec is the specification of the Kube cluster proxy resource. +type KubeClusterSpec struct { + // Mode is the mode of the KubeCluster proxy(Direct, Delegated). + // +kubebuilder:default=Direct + // +kubebuilder:validation:Enum=Direct;Delegated + Mode KubeClusterMode `json:"mode,omitempty"` + // SecretString is used to identify Target cluster in the backend for mount. + // Used only in Delegated mode. + // +optional + SecretString *string `json:"secretString,omitempty"` + // SecretRef is a reference to the secret containing the kubeconfig for the target cluster. + // Used only in Direct mode. + SecretRef *corev1.ObjectReference `json:"secretRef,omitempty"` +} + +// KubeClusterMode is the mode of the KubeCluster proxy. +type KubeClusterMode string + +const ( + // KubeClusterModeDirect represents the direct mode of the KubeCluster proxy. + KubeClusterModeDirect KubeClusterMode = "Direct" + // KubeClusterModeDelegated represents the delegated mode of the KubeCluster proxy. + KubeClusterModeDelegated KubeClusterMode = "Delegated" +) + +// KubeClusterStatus communicates the observed state of the Kube cluster proxy. +type KubeClusterStatus struct { + // url is the address under which the Kubernetes-cluster-like endpoint + // can be found. This URL can be used to access the cluster with standard Kubernetes + // client libraries and command line tools via proxy. + // + // +kubebuilder:format:uri + URL string `json:"URL,omitempty"` + + // Phase of the cluster proxy (Initializing, Ready). + // + // +kubebuilder:default=Initializing + Phase tenancyv1alpha1.MountPhaseType `json:"phase,omitempty"` + + // A timestamp indicating when the proxy last reported status. + // +optional + LastProxyHeartbeatTime *v1.Time `json:"lastProxyHeartbeatTime,omitempty"` + + // SecretString is mountpoint secret string for clients to mount. + // +optional + SecretString string `json:"secretString,omitempty"` + + // Current processing state of the Cluster proxy. + // +optional + Conditions conditionsv1alpha1.Conditions `json:"conditions,omitempty"` +} + +const ( + // ClusterReady represents readiness status of the KubeCluster proxy. + ClusterReady conditionsv1alpha1.ConditionType = "ClusterReady" + + // ClusterSecretReady represents readiness status of the TargetKubeCluster secret. + ClusterSecretReady conditionsv1alpha1.ConditionType = "ClusterSecretReady" + + // ClusterDeleted represents deletion status of the cleanup of the KubeCluster proxy. + ClusterDeleted conditionsv1alpha1.ConditionType = "ClusterDeleted" +) + +// KubeClusterList is a list of KubeCluster resources +// +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type KubeClusterList struct { + v1.TypeMeta `json:",inline"` + v1.ListMeta `json:"metadata"` + + Items []KubeCluster `json:"items"` +} + +func (in *KubeCluster) SetConditions(c conditionsv1alpha1.Conditions) { + in.Status.Conditions = c +} + +func (in *KubeCluster) GetConditions() conditionsv1alpha1.Conditions { + return in.Status.Conditions +} diff --git a/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1/types_vlustercluster.go b/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1/types_vlustercluster.go new file mode 100644 index 00000000000..fcc406f926e --- /dev/null +++ b/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1/types_vlustercluster.go @@ -0,0 +1,113 @@ +/* +Copyright 2023 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 v1alpha1 + +import ( + tenancyv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/tenancy/v1alpha1" + conditionsv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// VCluster describes the current VCluster proxy object. +// +// +crd +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster,categories=contrib +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=`.status.conditions[?(@.type=="ClusterReady")].status` +// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=`.status.phase` +type VCluster struct { + v1.TypeMeta `json:",inline"` + // +optional + v1.ObjectMeta `json:"metadata,omitempty"` + // +optional + Spec VClusterSpec `json:"spec,omitempty"` + // +optional + Status VClusterStatus `json:"status,omitempty"` +} + +// VClusterSpec is the specification of the VCluster cluster proxy resource. +type VClusterSpec struct { + // Version is the version of the VCluster proxy. + // +optional + // +kubebuilder:default="0.20.2" + Version string `json:"version,omitempty"` + // Mode is the mode of the KubeCluster proxy(Direct, Delegated). + // +kubebuilder:default=Delegated + // +kubebuilder:validation:Enum=Delegated + Mode KubeClusterMode `json:"mode,omitempty"` + // SecretString is used to identify Target cluster in the backend for mount. + // Used only in Delegated mode. + // +optional + SecretString *string `json:"secretString,omitempty"` + // SecretRef is a reference to the secret containing the kubeconfig for the target cluster. + // Used only in Direct mode. + SecretRef *corev1.ObjectReference `json:"secretRef,omitempty"` +} + +// VClusterMode is the mode of the VCluster proxy. +type VClusterMode string + +// VClusterStatus communicates the observed state of the VCluster cluster proxy. +type VClusterStatus struct { + // url is the address under which the Kubernetes-cluster-like endpoint + // can be found. This URL can be used to access the cluster with standard Kubernetes + // client libraries and command line tools via proxy. + // + // +kubebuilder:format:uri + URL string `json:"URL,omitempty"` + + // SecretString is the secret string used to identify the target cluster in the backend for mount. + // Used in both codes, as it is used to identify the target cluster in vcluster cluster pool. + // +optional + SecretString string `json:"secretString,omitempty"` + + // Phase of the cluster proxy (Initializing;Connecting;Ready;Unknown). + // + // +kubebuilder:default=Initializing + Phase tenancyv1alpha1.MountPhaseType `json:"phase,omitempty"` + + // A timestamp indicating when the proxy last reported status. + // +optional + LastProxyHeartbeatTime *v1.Time `json:"lastProxyHeartbeatTime,omitempty"` + + // Current processing state of the Cluster proxy. + // +optional + Conditions conditionsv1alpha1.Conditions `json:"conditions,omitempty"` +} + +// VClusterList is a list of VCluster resources +// +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type VClusterList struct { + v1.TypeMeta `json:",inline"` + v1.ListMeta `json:"metadata"` + + Items []VCluster `json:"items"` +} + +func (in *VCluster) SetConditions(c conditionsv1alpha1.Conditions) { + in.Status.Conditions = c +} + +func (in *VCluster) GetConditions() conditionsv1alpha1.Conditions { + return in.Status.Conditions +} diff --git a/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1/zz_generated.deepcopy.go b/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..3e355408e9d --- /dev/null +++ b/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,257 @@ +//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 deepcopy-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + conditionsv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + + v1 "k8s.io/api/core/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeCluster) DeepCopyInto(out *KubeCluster) { + *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 KubeCluster. +func (in *KubeCluster) DeepCopy() *KubeCluster { + if in == nil { + return nil + } + out := new(KubeCluster) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KubeCluster) 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 *KubeClusterList) DeepCopyInto(out *KubeClusterList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]KubeCluster, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeClusterList. +func (in *KubeClusterList) DeepCopy() *KubeClusterList { + if in == nil { + return nil + } + out := new(KubeClusterList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KubeClusterList) 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 *KubeClusterSpec) DeepCopyInto(out *KubeClusterSpec) { + *out = *in + if in.SecretString != nil { + in, out := &in.SecretString, &out.SecretString + *out = new(string) + **out = **in + } + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + *out = new(v1.ObjectReference) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeClusterSpec. +func (in *KubeClusterSpec) DeepCopy() *KubeClusterSpec { + if in == nil { + return nil + } + out := new(KubeClusterSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeClusterStatus) DeepCopyInto(out *KubeClusterStatus) { + *out = *in + if in.LastProxyHeartbeatTime != nil { + in, out := &in.LastProxyHeartbeatTime, &out.LastProxyHeartbeatTime + *out = (*in).DeepCopy() + } + 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]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeClusterStatus. +func (in *KubeClusterStatus) DeepCopy() *KubeClusterStatus { + if in == nil { + return nil + } + out := new(KubeClusterStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VCluster) DeepCopyInto(out *VCluster) { + *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 VCluster. +func (in *VCluster) DeepCopy() *VCluster { + if in == nil { + return nil + } + out := new(VCluster) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VCluster) 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 *VClusterList) DeepCopyInto(out *VClusterList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VCluster, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VClusterList. +func (in *VClusterList) DeepCopy() *VClusterList { + if in == nil { + return nil + } + out := new(VClusterList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VClusterList) 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 *VClusterSpec) DeepCopyInto(out *VClusterSpec) { + *out = *in + if in.SecretString != nil { + in, out := &in.SecretString, &out.SecretString + *out = new(string) + **out = **in + } + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + *out = new(v1.ObjectReference) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VClusterSpec. +func (in *VClusterSpec) DeepCopy() *VClusterSpec { + if in == nil { + return nil + } + out := new(VClusterSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VClusterStatus) DeepCopyInto(out *VClusterStatus) { + *out = *in + if in.LastProxyHeartbeatTime != nil { + in, out := &in.LastProxyHeartbeatTime, &out.LastProxyHeartbeatTime + *out = (*in).DeepCopy() + } + 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]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VClusterStatus. +func (in *VClusterStatus) DeepCopy() *VClusterStatus { + if in == nil { + return nil + } + out := new(VClusterStatus) + in.DeepCopyInto(out) + return out +} diff --git a/contrib/mounts-virtualworkspace/apis/targets/OWNERS b/contrib/mounts-virtualworkspace/apis/targets/OWNERS new file mode 100644 index 00000000000..1b4da8bace9 --- /dev/null +++ b/contrib/mounts-virtualworkspace/apis/targets/OWNERS @@ -0,0 +1,2 @@ +reviewers: +- mjudeikis diff --git a/contrib/mounts-virtualworkspace/apis/targets/register.go b/contrib/mounts-virtualworkspace/apis/targets/register.go new file mode 100644 index 00000000000..d361fb3518a --- /dev/null +++ b/contrib/mounts-virtualworkspace/apis/targets/register.go @@ -0,0 +1,23 @@ +/* +Copyright 2023 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 targets + +const ( + GroupName = "targets.contrib.kcp.io" + TargetKubeClusterKind = "TargetKubeCluster" + TargetVClusterKind = "TargetVCluster" +) diff --git a/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/doc.go b/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/doc.go new file mode 100644 index 00000000000..3503afea2db --- /dev/null +++ b/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2024 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. +*/ + +// +k8s:deepcopy-gen=package,register +// +groupName=targets.contrib.kcp.io +// +k8s:openapi-gen=true +package v1alpha1 diff --git a/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/helpers.go b/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/helpers.go new file mode 100644 index 00000000000..8f9ffd81068 --- /dev/null +++ b/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/helpers.go @@ -0,0 +1,38 @@ +/* +Copyright 2023 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 v1alpha1 + +import ( + "crypto/sha256" + "math/big" + + "github.com/kcp-dev/logicalcluster/v3" +) + +// ToProxyTargetKey hashes the Proxy workspace and the Proxy name to a string that is used to identify +// in a unique way the proxy in annotations/labels/finalizers. +func ToProxyTargetKey(clusterName logicalcluster.Name, name string) string { + hash := sha256.Sum224([]byte(clusterName.Path().Join(name).String())) + base62hash := toBase62(hash) + return base62hash +} + +func toBase62(hash [28]byte) string { + var i big.Int + i.SetBytes(hash[:]) + return i.Text(62) +} diff --git a/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/register.go b/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/register.go new file mode 100644 index 00000000000..7aa43ace2e0 --- /dev/null +++ b/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/register.go @@ -0,0 +1,55 @@ +/* +Copyright 2023 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 v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets" +) + +// SchemeGroupVersion is group version used to register these objects. +var SchemeGroupVersion = schema.GroupVersion{Group: targets.GroupName, Version: "v1alpha1"} + +// Kind takes an unqualified kind and returns back a Group qualified GroupKind. +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource. +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &TargetKubeCluster{}, + &TargetKubeClusterList{}, + &TargetVCluster{}, + &TargetVClusterList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/types.go b/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/types.go new file mode 100644 index 00000000000..3f86d30e581 --- /dev/null +++ b/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/types.go @@ -0,0 +1,8 @@ +package v1alpha1 + +const ( + + // InternalWorkspaceProxyKeyLabel is an internal label set on a WorkspaceProxy resource that contains the full hash of the WorkspaceProxyKey, generated with the ToProxyTargetKey(..) + // helper func, this label is used for reverse lookups of workspaceProxyKey to WorkspaceProxy. + InternalWorkspaceProxyKeyLabel = "internal.targets.contrib.kcp.io/key" +) diff --git a/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/types_target_kubecluster.go b/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/types_target_kubecluster.go new file mode 100644 index 00000000000..75e09ca4fe9 --- /dev/null +++ b/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/types_target_kubecluster.go @@ -0,0 +1,105 @@ +/* +Copyright 2023 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 v1alpha1 + +import ( + tenancyv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/tenancy/v1alpha1" + conditionsv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// KubeCluster describes the current KubeCluster target object. +// +// +crd +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster,categories=contrib +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=`.status.conditions[?(@.type=="ClusterReady")].status` +// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=`.status.phase` +type TargetKubeCluster struct { + v1.TypeMeta `json:",inline"` + // +optional + v1.ObjectMeta `json:"metadata,omitempty"` + // +optional + Spec TargetKubeClusterSpec `json:"spec,omitempty"` + // +optional + Status TargetKubeClusterStatus `json:"status,omitempty"` +} + +// TargetKubeClusterSpec is the specification of the Target Kube cluster proxy resource. +type TargetKubeClusterSpec struct { + // SecretRef is a reference to the secret containing the kubeconfig for the target cluster. + SecretRef corev1.ObjectReference `json:"secretRef,omitempty"` +} + +// TargetKubeClusterStatus communicates the observed state of the Kube cluster proxy. +type TargetKubeClusterStatus struct { + // Phase of the cluster proxy (Initializing, Ready). + // + // +kubebuilder:default=Initializing + Phase tenancyv1alpha1.MountPhaseType `json:"phase,omitempty"` + + // A timestamp indicating when the proxy last reported status. + // +optional + LastProxyHeartbeatTime *v1.Time `json:"lastProxyHeartbeatTime,omitempty"` + + // Current processing state of the Cluster proxy. + // +optional + Conditions conditionsv1alpha1.Conditions `json:"conditions,omitempty"` + + // SecretString is mountpoint secret string for clients to mount. + SecretString string `json:"secretString,omitempty"` + + // URL is the address under which mount should be using. + // +kubebuilder:format:uri + URL string `json:"URL,omitempty"` +} + +const ( + // ClusterReady represents readiness status of the TargetKubeCluster proxy. + ClusterReady conditionsv1alpha1.ConditionType = "ClusterReady" + + // ClusterSecretReady represents readiness status of the TargetKubeCluster secret. + ClusterSecretReady conditionsv1alpha1.ConditionType = "ClusterSecretReady" +) + +const ( + PhaseInitializing tenancyv1alpha1.MountPhaseType = "Initializing" + PhaseReady tenancyv1alpha1.MountPhaseType = "Ready" +) + +// TargetKubeClusterList is a list of TargetKubeCluster resources +// +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type TargetKubeClusterList struct { + v1.TypeMeta `json:",inline"` + v1.ListMeta `json:"metadata"` + + Items []TargetKubeCluster `json:"items"` +} + +func (in *TargetKubeCluster) SetConditions(c conditionsv1alpha1.Conditions) { + in.Status.Conditions = c +} + +func (in *TargetKubeCluster) GetConditions() conditionsv1alpha1.Conditions { + return in.Status.Conditions +} diff --git a/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/types_target_vcluster.go b/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/types_target_vcluster.go new file mode 100644 index 00000000000..4266f0baae4 --- /dev/null +++ b/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/types_target_vcluster.go @@ -0,0 +1,92 @@ +/* +Copyright 2023 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 v1alpha1 + +import ( + tenancyv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/tenancy/v1alpha1" + conditionsv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// TargetVCluster describes the current VCluster target object. +// +// +crd +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster,categories=contrib +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=`.status.conditions[?(@.type=="ClusterReady")].status` +// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=`.status.phase` +type TargetVCluster struct { + v1.TypeMeta `json:",inline"` + // +optional + v1.ObjectMeta `json:"metadata,omitempty"` + // +optional + Spec TargetVClusterSpec `json:"spec,omitempty"` + // +optional + Status TargetVClusterStatus `json:"status,omitempty"` +} + +// TargetVClusterSpec is the specification of the Target Kube cluster proxy resource. +type TargetVClusterSpec struct { + // SecretRef is a reference to the secret containing the kubeconfig for the target cluster. + SecretRef corev1.ObjectReference `json:"secretRef,omitempty"` +} + +// TargetVClusterStatus communicates the observed state of the Kube cluster proxy. +type TargetVClusterStatus struct { + // Phase of the cluster proxy (Initializing, Ready). + // + // +kubebuilder:default=Initializing + Phase tenancyv1alpha1.MountPhaseType `json:"phase,omitempty"` + + // A timestamp indicating when the proxy last reported status. + // +optional + LastProxyHeartbeatTime *v1.Time `json:"lastProxyHeartbeatTime,omitempty"` + + // Current processing state of the Cluster proxy. + // +optional + Conditions conditionsv1alpha1.Conditions `json:"conditions,omitempty"` + + // SecretString is mountpoint secret string for clients to mount. + SecretString string `json:"secretString,omitempty"` + + // URL is the address under which mount should be using. + // +kubebuilder:format:uri + URL string `json:"URL,omitempty"` +} + +// TargetVClusterList is a list of TargetVCluster resources +// +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type TargetVClusterList struct { + v1.TypeMeta `json:",inline"` + v1.ListMeta `json:"metadata"` + + Items []TargetVCluster `json:"items"` +} + +func (in *TargetVCluster) SetConditions(c conditionsv1alpha1.Conditions) { + in.Status.Conditions = c +} + +func (in *TargetVCluster) GetConditions() conditionsv1alpha1.Conditions { + return in.Status.Conditions +} diff --git a/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/zz_generated.deepcopy.go b/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..dffdee074f7 --- /dev/null +++ b/contrib/mounts-virtualworkspace/apis/targets/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,238 @@ +//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 deepcopy-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + conditionsv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TargetKubeCluster) DeepCopyInto(out *TargetKubeCluster) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetKubeCluster. +func (in *TargetKubeCluster) DeepCopy() *TargetKubeCluster { + if in == nil { + return nil + } + out := new(TargetKubeCluster) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TargetKubeCluster) 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 *TargetKubeClusterList) DeepCopyInto(out *TargetKubeClusterList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]TargetKubeCluster, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetKubeClusterList. +func (in *TargetKubeClusterList) DeepCopy() *TargetKubeClusterList { + if in == nil { + return nil + } + out := new(TargetKubeClusterList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TargetKubeClusterList) 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 *TargetKubeClusterSpec) DeepCopyInto(out *TargetKubeClusterSpec) { + *out = *in + out.SecretRef = in.SecretRef + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetKubeClusterSpec. +func (in *TargetKubeClusterSpec) DeepCopy() *TargetKubeClusterSpec { + if in == nil { + return nil + } + out := new(TargetKubeClusterSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TargetKubeClusterStatus) DeepCopyInto(out *TargetKubeClusterStatus) { + *out = *in + if in.LastProxyHeartbeatTime != nil { + in, out := &in.LastProxyHeartbeatTime, &out.LastProxyHeartbeatTime + *out = (*in).DeepCopy() + } + 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]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetKubeClusterStatus. +func (in *TargetKubeClusterStatus) DeepCopy() *TargetKubeClusterStatus { + if in == nil { + return nil + } + out := new(TargetKubeClusterStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TargetVCluster) DeepCopyInto(out *TargetVCluster) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetVCluster. +func (in *TargetVCluster) DeepCopy() *TargetVCluster { + if in == nil { + return nil + } + out := new(TargetVCluster) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TargetVCluster) 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 *TargetVClusterList) DeepCopyInto(out *TargetVClusterList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]TargetVCluster, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetVClusterList. +func (in *TargetVClusterList) DeepCopy() *TargetVClusterList { + if in == nil { + return nil + } + out := new(TargetVClusterList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TargetVClusterList) 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 *TargetVClusterSpec) DeepCopyInto(out *TargetVClusterSpec) { + *out = *in + out.SecretRef = in.SecretRef + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetVClusterSpec. +func (in *TargetVClusterSpec) DeepCopy() *TargetVClusterSpec { + if in == nil { + return nil + } + out := new(TargetVClusterSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TargetVClusterStatus) DeepCopyInto(out *TargetVClusterStatus) { + *out = *in + if in.LastProxyHeartbeatTime != nil { + in, out := &in.LastProxyHeartbeatTime, &out.LastProxyHeartbeatTime + *out = (*in).DeepCopy() + } + 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]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetVClusterStatus. +func (in *TargetVClusterStatus) DeepCopy() *TargetVClusterStatus { + if in == nil { + return nil + } + out := new(TargetVClusterStatus) + in.DeepCopyInto(out) + return out +} diff --git a/contrib/mounts-virtualworkspace/assets/path-mapping.yaml b/contrib/mounts-virtualworkspace/assets/path-mapping.yaml new file mode 100644 index 00000000000..18d081c9620 --- /dev/null +++ b/contrib/mounts-virtualworkspace/assets/path-mapping.yaml @@ -0,0 +1,5 @@ +- path: /services/cluster-proxy + backend: https://localhost:6444 + backend_server_ca: ../../.kcp/server.crt + proxy_client_cert: ../../.kcp/server.crt + proxy_client_key: ../../.kcp/server.key diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/conditions/v1alpha1/condition.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/conditions/v1alpha1/condition.go new file mode 100644 index 00000000000..b86f0510b86 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/conditions/v1alpha1/condition.go @@ -0,0 +1,91 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// ConditionApplyConfiguration represents a declarative configuration of the Condition type for use +// with apply. +type ConditionApplyConfiguration struct { + Type *v1alpha1.ConditionType `json:"type,omitempty"` + Status *v1.ConditionStatus `json:"status,omitempty"` + Severity *v1alpha1.ConditionSeverity `json:"severity,omitempty"` + LastTransitionTime *metav1.Time `json:"lastTransitionTime,omitempty"` + Reason *string `json:"reason,omitempty"` + Message *string `json:"message,omitempty"` +} + +// ConditionApplyConfiguration constructs a declarative configuration of the Condition type for use with +// apply. +func Condition() *ConditionApplyConfiguration { + return &ConditionApplyConfiguration{} +} + +// WithType sets the Type field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Type field is set to the value of the last call. +func (b *ConditionApplyConfiguration) WithType(value v1alpha1.ConditionType) *ConditionApplyConfiguration { + b.Type = &value + return b +} + +// WithStatus sets the Status field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Status field is set to the value of the last call. +func (b *ConditionApplyConfiguration) WithStatus(value v1.ConditionStatus) *ConditionApplyConfiguration { + b.Status = &value + return b +} + +// WithSeverity sets the Severity field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Severity field is set to the value of the last call. +func (b *ConditionApplyConfiguration) WithSeverity(value v1alpha1.ConditionSeverity) *ConditionApplyConfiguration { + b.Severity = &value + return b +} + +// WithLastTransitionTime sets the LastTransitionTime field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the LastTransitionTime field is set to the value of the last call. +func (b *ConditionApplyConfiguration) WithLastTransitionTime(value metav1.Time) *ConditionApplyConfiguration { + b.LastTransitionTime = &value + return b +} + +// WithReason sets the Reason field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Reason field is set to the value of the last call. +func (b *ConditionApplyConfiguration) WithReason(value string) *ConditionApplyConfiguration { + b.Reason = &value + return b +} + +// WithMessage sets the Message field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Message field is set to the value of the last call. +func (b *ConditionApplyConfiguration) WithMessage(value string) *ConditionApplyConfiguration { + b.Message = &value + return b +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/internal/internal.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/internal/internal.go new file mode 100644 index 00000000000..1bcc7002d26 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/internal/internal.go @@ -0,0 +1,62 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package internal + +import ( + "fmt" + "sync" + + typed "sigs.k8s.io/structured-merge-diff/v4/typed" +) + +func Parser() *typed.Parser { + parserOnce.Do(func() { + var err error + parser, err = typed.NewParser(schemaYAML) + if err != nil { + panic(fmt.Sprintf("Failed to parse schema: %v", err)) + } + }) + return parser +} + +var parserOnce sync.Once +var parser *typed.Parser +var schemaYAML = typed.YAMLObject(`types: +- name: __untyped_atomic_ + scalar: untyped + list: + elementType: + namedType: __untyped_atomic_ + elementRelationship: atomic + map: + elementType: + namedType: __untyped_atomic_ + elementRelationship: atomic +- name: __untyped_deduced_ + scalar: untyped + list: + elementType: + namedType: __untyped_atomic_ + elementRelationship: atomic + map: + elementType: + namedType: __untyped_deduced_ + elementRelationship: separable +`) diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/condition.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/condition.go new file mode 100644 index 00000000000..823954bdd16 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/condition.go @@ -0,0 +1,88 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// ConditionApplyConfiguration represents a declarative configuration of the Condition type for use +// with apply. +type ConditionApplyConfiguration struct { + Type *string `json:"type,omitempty"` + Status *v1.ConditionStatus `json:"status,omitempty"` + ObservedGeneration *int64 `json:"observedGeneration,omitempty"` + LastTransitionTime *v1.Time `json:"lastTransitionTime,omitempty"` + Reason *string `json:"reason,omitempty"` + Message *string `json:"message,omitempty"` +} + +// ConditionApplyConfiguration constructs a declarative configuration of the Condition type for use with +// apply. +func Condition() *ConditionApplyConfiguration { + return &ConditionApplyConfiguration{} +} + +// WithType sets the Type field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Type field is set to the value of the last call. +func (b *ConditionApplyConfiguration) WithType(value string) *ConditionApplyConfiguration { + b.Type = &value + return b +} + +// WithStatus sets the Status field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Status field is set to the value of the last call. +func (b *ConditionApplyConfiguration) WithStatus(value v1.ConditionStatus) *ConditionApplyConfiguration { + b.Status = &value + return b +} + +// WithObservedGeneration sets the ObservedGeneration field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ObservedGeneration field is set to the value of the last call. +func (b *ConditionApplyConfiguration) WithObservedGeneration(value int64) *ConditionApplyConfiguration { + b.ObservedGeneration = &value + return b +} + +// WithLastTransitionTime sets the LastTransitionTime field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the LastTransitionTime field is set to the value of the last call. +func (b *ConditionApplyConfiguration) WithLastTransitionTime(value v1.Time) *ConditionApplyConfiguration { + b.LastTransitionTime = &value + return b +} + +// WithReason sets the Reason field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Reason field is set to the value of the last call. +func (b *ConditionApplyConfiguration) WithReason(value string) *ConditionApplyConfiguration { + b.Reason = &value + return b +} + +// WithMessage sets the Message field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Message field is set to the value of the last call. +func (b *ConditionApplyConfiguration) WithMessage(value string) *ConditionApplyConfiguration { + b.Message = &value + return b +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/deleteoptions.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/deleteoptions.go new file mode 100644 index 00000000000..e5135adb4e7 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/deleteoptions.go @@ -0,0 +1,101 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// DeleteOptionsApplyConfiguration represents a declarative configuration of the DeleteOptions type for use +// with apply. +type DeleteOptionsApplyConfiguration struct { + TypeMetaApplyConfiguration `json:",inline"` + GracePeriodSeconds *int64 `json:"gracePeriodSeconds,omitempty"` + Preconditions *metav1.Preconditions `json:"preconditions,omitempty"` + OrphanDependents *bool `json:"orphanDependents,omitempty"` + PropagationPolicy *metav1.DeletionPropagation `json:"propagationPolicy,omitempty"` + DryRun []string `json:"dryRun,omitempty"` +} + +// DeleteOptionsApplyConfiguration constructs a declarative configuration of the DeleteOptions type for use with +// apply. +func DeleteOptions() *DeleteOptionsApplyConfiguration { + b := &DeleteOptionsApplyConfiguration{} + b.WithKind("DeleteOptions") + b.WithAPIVersion("meta.k8s.io/v1") + return b +} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *DeleteOptionsApplyConfiguration) WithKind(value string) *DeleteOptionsApplyConfiguration { + b.Kind = &value + return b +} + +// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the APIVersion field is set to the value of the last call. +func (b *DeleteOptionsApplyConfiguration) WithAPIVersion(value string) *DeleteOptionsApplyConfiguration { + b.APIVersion = &value + return b +} + +// WithGracePeriodSeconds sets the GracePeriodSeconds field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the GracePeriodSeconds field is set to the value of the last call. +func (b *DeleteOptionsApplyConfiguration) WithGracePeriodSeconds(value int64) *DeleteOptionsApplyConfiguration { + b.GracePeriodSeconds = &value + return b +} + +// WithPreconditions sets the Preconditions field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Preconditions field is set to the value of the last call. +func (b *DeleteOptionsApplyConfiguration) WithPreconditions(value metav1.Preconditions) *DeleteOptionsApplyConfiguration { + b.Preconditions = &value + return b +} + +// WithOrphanDependents sets the OrphanDependents field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the OrphanDependents field is set to the value of the last call. +func (b *DeleteOptionsApplyConfiguration) WithOrphanDependents(value bool) *DeleteOptionsApplyConfiguration { + b.OrphanDependents = &value + return b +} + +// WithPropagationPolicy sets the PropagationPolicy field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the PropagationPolicy field is set to the value of the last call. +func (b *DeleteOptionsApplyConfiguration) WithPropagationPolicy(value metav1.DeletionPropagation) *DeleteOptionsApplyConfiguration { + b.PropagationPolicy = &value + return b +} + +// WithDryRun adds the given value to the DryRun field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the DryRun field. +func (b *DeleteOptionsApplyConfiguration) WithDryRun(values ...string) *DeleteOptionsApplyConfiguration { + for i := range values { + b.DryRun = append(b.DryRun, values[i]) + } + return b +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/labelselector.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/labelselector.go new file mode 100644 index 00000000000..47dcc5de090 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/labelselector.go @@ -0,0 +1,63 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1 + +import ( + v1 "k8s.io/client-go/applyconfigurations/meta/v1" +) + +// LabelSelectorApplyConfiguration represents a declarative configuration of the LabelSelector type for use +// with apply. +type LabelSelectorApplyConfiguration struct { + MatchLabels map[string]string `json:"matchLabels,omitempty"` + MatchExpressions []v1.LabelSelectorRequirementApplyConfiguration `json:"matchExpressions,omitempty"` +} + +// LabelSelectorApplyConfiguration constructs a declarative configuration of the LabelSelector type for use with +// apply. +func LabelSelector() *LabelSelectorApplyConfiguration { + return &LabelSelectorApplyConfiguration{} +} + +// WithMatchLabels puts the entries into the MatchLabels field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the MatchLabels field, +// overwriting an existing map entries in MatchLabels field with the same key. +func (b *LabelSelectorApplyConfiguration) WithMatchLabels(entries map[string]string) *LabelSelectorApplyConfiguration { + if b.MatchLabels == nil && len(entries) > 0 { + b.MatchLabels = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.MatchLabels[k] = v + } + return b +} + +// WithMatchExpressions adds the given value to the MatchExpressions field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the MatchExpressions field. +func (b *LabelSelectorApplyConfiguration) WithMatchExpressions(values ...*v1.LabelSelectorRequirementApplyConfiguration) *LabelSelectorApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithMatchExpressions") + } + b.MatchExpressions = append(b.MatchExpressions, *values[i]) + } + return b +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/labelselectorrequirement.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/labelselectorrequirement.go new file mode 100644 index 00000000000..4da2259b1f6 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/labelselectorrequirement.go @@ -0,0 +1,63 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// LabelSelectorRequirementApplyConfiguration represents a declarative configuration of the LabelSelectorRequirement type for use +// with apply. +type LabelSelectorRequirementApplyConfiguration struct { + Key *string `json:"key,omitempty"` + Operator *v1.LabelSelectorOperator `json:"operator,omitempty"` + Values []string `json:"values,omitempty"` +} + +// LabelSelectorRequirementApplyConfiguration constructs a declarative configuration of the LabelSelectorRequirement type for use with +// apply. +func LabelSelectorRequirement() *LabelSelectorRequirementApplyConfiguration { + return &LabelSelectorRequirementApplyConfiguration{} +} + +// WithKey sets the Key field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Key field is set to the value of the last call. +func (b *LabelSelectorRequirementApplyConfiguration) WithKey(value string) *LabelSelectorRequirementApplyConfiguration { + b.Key = &value + return b +} + +// WithOperator sets the Operator field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Operator field is set to the value of the last call. +func (b *LabelSelectorRequirementApplyConfiguration) WithOperator(value v1.LabelSelectorOperator) *LabelSelectorRequirementApplyConfiguration { + b.Operator = &value + return b +} + +// WithValues adds the given value to the Values field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Values field. +func (b *LabelSelectorRequirementApplyConfiguration) WithValues(values ...string) *LabelSelectorRequirementApplyConfiguration { + for i := range values { + b.Values = append(b.Values, values[i]) + } + return b +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/managedfieldsentry.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/managedfieldsentry.go new file mode 100644 index 00000000000..87bf99be61f --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/managedfieldsentry.go @@ -0,0 +1,97 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// ManagedFieldsEntryApplyConfiguration represents a declarative configuration of the ManagedFieldsEntry type for use +// with apply. +type ManagedFieldsEntryApplyConfiguration struct { + Manager *string `json:"manager,omitempty"` + Operation *v1.ManagedFieldsOperationType `json:"operation,omitempty"` + APIVersion *string `json:"apiVersion,omitempty"` + Time *v1.Time `json:"time,omitempty"` + FieldsType *string `json:"fieldsType,omitempty"` + FieldsV1 *v1.FieldsV1 `json:"fieldsV1,omitempty"` + Subresource *string `json:"subresource,omitempty"` +} + +// ManagedFieldsEntryApplyConfiguration constructs a declarative configuration of the ManagedFieldsEntry type for use with +// apply. +func ManagedFieldsEntry() *ManagedFieldsEntryApplyConfiguration { + return &ManagedFieldsEntryApplyConfiguration{} +} + +// WithManager sets the Manager field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Manager field is set to the value of the last call. +func (b *ManagedFieldsEntryApplyConfiguration) WithManager(value string) *ManagedFieldsEntryApplyConfiguration { + b.Manager = &value + return b +} + +// WithOperation sets the Operation field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Operation field is set to the value of the last call. +func (b *ManagedFieldsEntryApplyConfiguration) WithOperation(value v1.ManagedFieldsOperationType) *ManagedFieldsEntryApplyConfiguration { + b.Operation = &value + return b +} + +// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the APIVersion field is set to the value of the last call. +func (b *ManagedFieldsEntryApplyConfiguration) WithAPIVersion(value string) *ManagedFieldsEntryApplyConfiguration { + b.APIVersion = &value + return b +} + +// WithTime sets the Time field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Time field is set to the value of the last call. +func (b *ManagedFieldsEntryApplyConfiguration) WithTime(value v1.Time) *ManagedFieldsEntryApplyConfiguration { + b.Time = &value + return b +} + +// WithFieldsType sets the FieldsType field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the FieldsType field is set to the value of the last call. +func (b *ManagedFieldsEntryApplyConfiguration) WithFieldsType(value string) *ManagedFieldsEntryApplyConfiguration { + b.FieldsType = &value + return b +} + +// WithFieldsV1 sets the FieldsV1 field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the FieldsV1 field is set to the value of the last call. +func (b *ManagedFieldsEntryApplyConfiguration) WithFieldsV1(value v1.FieldsV1) *ManagedFieldsEntryApplyConfiguration { + b.FieldsV1 = &value + return b +} + +// WithSubresource sets the Subresource field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Subresource field is set to the value of the last call. +func (b *ManagedFieldsEntryApplyConfiguration) WithSubresource(value string) *ManagedFieldsEntryApplyConfiguration { + b.Subresource = &value + return b +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/objectmeta.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/objectmeta.go new file mode 100644 index 00000000000..6b416cdaa7a --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/objectmeta.go @@ -0,0 +1,176 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" +) + +// ObjectMetaApplyConfiguration represents a declarative configuration of the ObjectMeta type for use +// with apply. +type ObjectMetaApplyConfiguration struct { + Name *string `json:"name,omitempty"` + GenerateName *string `json:"generateName,omitempty"` + Namespace *string `json:"namespace,omitempty"` + UID *types.UID `json:"uid,omitempty"` + ResourceVersion *string `json:"resourceVersion,omitempty"` + Generation *int64 `json:"generation,omitempty"` + CreationTimestamp *v1.Time `json:"creationTimestamp,omitempty"` + DeletionTimestamp *v1.Time `json:"deletionTimestamp,omitempty"` + DeletionGracePeriodSeconds *int64 `json:"deletionGracePeriodSeconds,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + Annotations map[string]string `json:"annotations,omitempty"` + OwnerReferences []OwnerReferenceApplyConfiguration `json:"ownerReferences,omitempty"` + Finalizers []string `json:"finalizers,omitempty"` +} + +// ObjectMetaApplyConfiguration constructs a declarative configuration of the ObjectMeta type for use with +// apply. +func ObjectMeta() *ObjectMetaApplyConfiguration { + return &ObjectMetaApplyConfiguration{} +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *ObjectMetaApplyConfiguration) WithName(value string) *ObjectMetaApplyConfiguration { + b.Name = &value + return b +} + +// WithGenerateName sets the GenerateName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the GenerateName field is set to the value of the last call. +func (b *ObjectMetaApplyConfiguration) WithGenerateName(value string) *ObjectMetaApplyConfiguration { + b.GenerateName = &value + return b +} + +// WithNamespace sets the Namespace field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Namespace field is set to the value of the last call. +func (b *ObjectMetaApplyConfiguration) WithNamespace(value string) *ObjectMetaApplyConfiguration { + b.Namespace = &value + return b +} + +// WithUID sets the UID field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UID field is set to the value of the last call. +func (b *ObjectMetaApplyConfiguration) WithUID(value types.UID) *ObjectMetaApplyConfiguration { + b.UID = &value + return b +} + +// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ResourceVersion field is set to the value of the last call. +func (b *ObjectMetaApplyConfiguration) WithResourceVersion(value string) *ObjectMetaApplyConfiguration { + b.ResourceVersion = &value + return b +} + +// WithGeneration sets the Generation field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Generation field is set to the value of the last call. +func (b *ObjectMetaApplyConfiguration) WithGeneration(value int64) *ObjectMetaApplyConfiguration { + b.Generation = &value + return b +} + +// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the CreationTimestamp field is set to the value of the last call. +func (b *ObjectMetaApplyConfiguration) WithCreationTimestamp(value v1.Time) *ObjectMetaApplyConfiguration { + b.CreationTimestamp = &value + return b +} + +// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionTimestamp field is set to the value of the last call. +func (b *ObjectMetaApplyConfiguration) WithDeletionTimestamp(value v1.Time) *ObjectMetaApplyConfiguration { + b.DeletionTimestamp = &value + return b +} + +// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call. +func (b *ObjectMetaApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *ObjectMetaApplyConfiguration { + b.DeletionGracePeriodSeconds = &value + return b +} + +// WithLabels puts the entries into the Labels field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Labels field, +// overwriting an existing map entries in Labels field with the same key. +func (b *ObjectMetaApplyConfiguration) WithLabels(entries map[string]string) *ObjectMetaApplyConfiguration { + if b.Labels == nil && len(entries) > 0 { + b.Labels = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Labels[k] = v + } + return b +} + +// WithAnnotations puts the entries into the Annotations field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Annotations field, +// overwriting an existing map entries in Annotations field with the same key. +func (b *ObjectMetaApplyConfiguration) WithAnnotations(entries map[string]string) *ObjectMetaApplyConfiguration { + if b.Annotations == nil && len(entries) > 0 { + b.Annotations = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Annotations[k] = v + } + return b +} + +// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the OwnerReferences field. +func (b *ObjectMetaApplyConfiguration) WithOwnerReferences(values ...*OwnerReferenceApplyConfiguration) *ObjectMetaApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithOwnerReferences") + } + b.OwnerReferences = append(b.OwnerReferences, *values[i]) + } + return b +} + +// WithFinalizers adds the given value to the Finalizers field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Finalizers field. +func (b *ObjectMetaApplyConfiguration) WithFinalizers(values ...string) *ObjectMetaApplyConfiguration { + for i := range values { + b.Finalizers = append(b.Finalizers, values[i]) + } + return b +} + +// GetName retrieves the value of the Name field in the declarative configuration. +func (b *ObjectMetaApplyConfiguration) GetName() *string { + return b.Name +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/ownerreference.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/ownerreference.go new file mode 100644 index 00000000000..70c7ba34a25 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/ownerreference.go @@ -0,0 +1,88 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1 + +import ( + types "k8s.io/apimachinery/pkg/types" +) + +// OwnerReferenceApplyConfiguration represents a declarative configuration of the OwnerReference type for use +// with apply. +type OwnerReferenceApplyConfiguration struct { + APIVersion *string `json:"apiVersion,omitempty"` + Kind *string `json:"kind,omitempty"` + Name *string `json:"name,omitempty"` + UID *types.UID `json:"uid,omitempty"` + Controller *bool `json:"controller,omitempty"` + BlockOwnerDeletion *bool `json:"blockOwnerDeletion,omitempty"` +} + +// OwnerReferenceApplyConfiguration constructs a declarative configuration of the OwnerReference type for use with +// apply. +func OwnerReference() *OwnerReferenceApplyConfiguration { + return &OwnerReferenceApplyConfiguration{} +} + +// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the APIVersion field is set to the value of the last call. +func (b *OwnerReferenceApplyConfiguration) WithAPIVersion(value string) *OwnerReferenceApplyConfiguration { + b.APIVersion = &value + return b +} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *OwnerReferenceApplyConfiguration) WithKind(value string) *OwnerReferenceApplyConfiguration { + b.Kind = &value + return b +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *OwnerReferenceApplyConfiguration) WithName(value string) *OwnerReferenceApplyConfiguration { + b.Name = &value + return b +} + +// WithUID sets the UID field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UID field is set to the value of the last call. +func (b *OwnerReferenceApplyConfiguration) WithUID(value types.UID) *OwnerReferenceApplyConfiguration { + b.UID = &value + return b +} + +// WithController sets the Controller field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Controller field is set to the value of the last call. +func (b *OwnerReferenceApplyConfiguration) WithController(value bool) *OwnerReferenceApplyConfiguration { + b.Controller = &value + return b +} + +// WithBlockOwnerDeletion sets the BlockOwnerDeletion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the BlockOwnerDeletion field is set to the value of the last call. +func (b *OwnerReferenceApplyConfiguration) WithBlockOwnerDeletion(value bool) *OwnerReferenceApplyConfiguration { + b.BlockOwnerDeletion = &value + return b +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/typemeta.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/typemeta.go new file mode 100644 index 00000000000..58c56d67ce4 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1/typemeta.go @@ -0,0 +1,48 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1 + +// TypeMetaApplyConfiguration represents a declarative configuration of the TypeMeta type for use +// with apply. +type TypeMetaApplyConfiguration struct { + Kind *string `json:"kind,omitempty"` + APIVersion *string `json:"apiVersion,omitempty"` +} + +// TypeMetaApplyConfiguration constructs a declarative configuration of the TypeMeta type for use with +// apply. +func TypeMeta() *TypeMetaApplyConfiguration { + return &TypeMetaApplyConfiguration{} +} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *TypeMetaApplyConfiguration) WithKind(value string) *TypeMetaApplyConfiguration { + b.Kind = &value + return b +} + +// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the APIVersion field is set to the value of the last call. +func (b *TypeMetaApplyConfiguration) WithAPIVersion(value string) *TypeMetaApplyConfiguration { + b.APIVersion = &value + return b +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1/kubecluster.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1/kubecluster.go new file mode 100644 index 00000000000..1cee85304c6 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1/kubecluster.go @@ -0,0 +1,225 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + + v1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1" +) + +// KubeClusterApplyConfiguration represents a declarative configuration of the KubeCluster type for use +// with apply. +type KubeClusterApplyConfiguration struct { + v1.TypeMetaApplyConfiguration `json:",inline"` + *v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"` + Spec *KubeClusterSpecApplyConfiguration `json:"spec,omitempty"` + Status *KubeClusterStatusApplyConfiguration `json:"status,omitempty"` +} + +// KubeCluster constructs a declarative configuration of the KubeCluster type for use with +// apply. +func KubeCluster(name string) *KubeClusterApplyConfiguration { + b := &KubeClusterApplyConfiguration{} + b.WithName(name) + b.WithKind("KubeCluster") + b.WithAPIVersion("mounts.contrib.kcp.io/v1alpha1") + return b +} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *KubeClusterApplyConfiguration) WithKind(value string) *KubeClusterApplyConfiguration { + b.Kind = &value + return b +} + +// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the APIVersion field is set to the value of the last call. +func (b *KubeClusterApplyConfiguration) WithAPIVersion(value string) *KubeClusterApplyConfiguration { + b.APIVersion = &value + return b +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *KubeClusterApplyConfiguration) WithName(value string) *KubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Name = &value + return b +} + +// WithGenerateName sets the GenerateName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the GenerateName field is set to the value of the last call. +func (b *KubeClusterApplyConfiguration) WithGenerateName(value string) *KubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.GenerateName = &value + return b +} + +// WithNamespace sets the Namespace field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Namespace field is set to the value of the last call. +func (b *KubeClusterApplyConfiguration) WithNamespace(value string) *KubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Namespace = &value + return b +} + +// WithUID sets the UID field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UID field is set to the value of the last call. +func (b *KubeClusterApplyConfiguration) WithUID(value types.UID) *KubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.UID = &value + return b +} + +// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ResourceVersion field is set to the value of the last call. +func (b *KubeClusterApplyConfiguration) WithResourceVersion(value string) *KubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ResourceVersion = &value + return b +} + +// WithGeneration sets the Generation field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Generation field is set to the value of the last call. +func (b *KubeClusterApplyConfiguration) WithGeneration(value int64) *KubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Generation = &value + return b +} + +// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the CreationTimestamp field is set to the value of the last call. +func (b *KubeClusterApplyConfiguration) WithCreationTimestamp(value metav1.Time) *KubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.CreationTimestamp = &value + return b +} + +// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionTimestamp field is set to the value of the last call. +func (b *KubeClusterApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *KubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.DeletionTimestamp = &value + return b +} + +// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call. +func (b *KubeClusterApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *KubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.DeletionGracePeriodSeconds = &value + return b +} + +// WithLabels puts the entries into the Labels field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Labels field, +// overwriting an existing map entries in Labels field with the same key. +func (b *KubeClusterApplyConfiguration) WithLabels(entries map[string]string) *KubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.Labels == nil && len(entries) > 0 { + b.Labels = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Labels[k] = v + } + return b +} + +// WithAnnotations puts the entries into the Annotations field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Annotations field, +// overwriting an existing map entries in Annotations field with the same key. +func (b *KubeClusterApplyConfiguration) WithAnnotations(entries map[string]string) *KubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.Annotations == nil && len(entries) > 0 { + b.Annotations = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Annotations[k] = v + } + return b +} + +// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the OwnerReferences field. +func (b *KubeClusterApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *KubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + if values[i] == nil { + panic("nil value passed to WithOwnerReferences") + } + b.OwnerReferences = append(b.OwnerReferences, *values[i]) + } + return b +} + +// WithFinalizers adds the given value to the Finalizers field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Finalizers field. +func (b *KubeClusterApplyConfiguration) WithFinalizers(values ...string) *KubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + b.Finalizers = append(b.Finalizers, values[i]) + } + return b +} + +func (b *KubeClusterApplyConfiguration) ensureObjectMetaApplyConfigurationExists() { + if b.ObjectMetaApplyConfiguration == nil { + b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{} + } +} + +// WithSpec sets the Spec field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Spec field is set to the value of the last call. +func (b *KubeClusterApplyConfiguration) WithSpec(value *KubeClusterSpecApplyConfiguration) *KubeClusterApplyConfiguration { + b.Spec = value + return b +} + +// WithStatus sets the Status field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Status field is set to the value of the last call. +func (b *KubeClusterApplyConfiguration) WithStatus(value *KubeClusterStatusApplyConfiguration) *KubeClusterApplyConfiguration { + b.Status = value + return b +} + +// GetName retrieves the value of the Name field in the declarative configuration. +func (b *KubeClusterApplyConfiguration) GetName() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.Name +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1/kubeclusterspec.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1/kubeclusterspec.go new file mode 100644 index 00000000000..d035700823b --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1/kubeclusterspec.go @@ -0,0 +1,63 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "k8s.io/api/core/v1" + + v1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" +) + +// KubeClusterSpecApplyConfiguration represents a declarative configuration of the KubeClusterSpec type for use +// with apply. +type KubeClusterSpecApplyConfiguration struct { + Mode *v1alpha1.KubeClusterMode `json:"mode,omitempty"` + SecretString *string `json:"secretString,omitempty"` + SecretRef *v1.ObjectReference `json:"secretRef,omitempty"` +} + +// KubeClusterSpecApplyConfiguration constructs a declarative configuration of the KubeClusterSpec type for use with +// apply. +func KubeClusterSpec() *KubeClusterSpecApplyConfiguration { + return &KubeClusterSpecApplyConfiguration{} +} + +// WithMode sets the Mode field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Mode field is set to the value of the last call. +func (b *KubeClusterSpecApplyConfiguration) WithMode(value v1alpha1.KubeClusterMode) *KubeClusterSpecApplyConfiguration { + b.Mode = &value + return b +} + +// WithSecretString sets the SecretString field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the SecretString field is set to the value of the last call. +func (b *KubeClusterSpecApplyConfiguration) WithSecretString(value string) *KubeClusterSpecApplyConfiguration { + b.SecretString = &value + return b +} + +// WithSecretRef sets the SecretRef field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the SecretRef field is set to the value of the last call. +func (b *KubeClusterSpecApplyConfiguration) WithSecretRef(value v1.ObjectReference) *KubeClusterSpecApplyConfiguration { + b.SecretRef = &value + return b +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1/kubeclusterstatus.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1/kubeclusterstatus.go new file mode 100644 index 00000000000..a575e3b49ad --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1/kubeclusterstatus.go @@ -0,0 +1,82 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/kcp-dev/kcp/sdk/apis/tenancy/v1alpha1" + conditionsv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// KubeClusterStatusApplyConfiguration represents a declarative configuration of the KubeClusterStatus type for use +// with apply. +type KubeClusterStatusApplyConfiguration struct { + URL *string `json:"URL,omitempty"` + Phase *v1alpha1.MountPhaseType `json:"phase,omitempty"` + LastProxyHeartbeatTime *v1.Time `json:"lastProxyHeartbeatTime,omitempty"` + SecretString *string `json:"secretString,omitempty"` + Conditions *conditionsv1alpha1.Conditions `json:"conditions,omitempty"` +} + +// KubeClusterStatusApplyConfiguration constructs a declarative configuration of the KubeClusterStatus type for use with +// apply. +func KubeClusterStatus() *KubeClusterStatusApplyConfiguration { + return &KubeClusterStatusApplyConfiguration{} +} + +// WithURL sets the URL field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the URL field is set to the value of the last call. +func (b *KubeClusterStatusApplyConfiguration) WithURL(value string) *KubeClusterStatusApplyConfiguration { + b.URL = &value + return b +} + +// WithPhase sets the Phase field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Phase field is set to the value of the last call. +func (b *KubeClusterStatusApplyConfiguration) WithPhase(value v1alpha1.MountPhaseType) *KubeClusterStatusApplyConfiguration { + b.Phase = &value + return b +} + +// WithLastProxyHeartbeatTime sets the LastProxyHeartbeatTime field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the LastProxyHeartbeatTime field is set to the value of the last call. +func (b *KubeClusterStatusApplyConfiguration) WithLastProxyHeartbeatTime(value v1.Time) *KubeClusterStatusApplyConfiguration { + b.LastProxyHeartbeatTime = &value + return b +} + +// WithSecretString sets the SecretString field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the SecretString field is set to the value of the last call. +func (b *KubeClusterStatusApplyConfiguration) WithSecretString(value string) *KubeClusterStatusApplyConfiguration { + b.SecretString = &value + return b +} + +// WithConditions sets the Conditions field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Conditions field is set to the value of the last call. +func (b *KubeClusterStatusApplyConfiguration) WithConditions(value conditionsv1alpha1.Conditions) *KubeClusterStatusApplyConfiguration { + b.Conditions = &value + return b +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1/vcluster.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1/vcluster.go new file mode 100644 index 00000000000..b9ba3eeac2b --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1/vcluster.go @@ -0,0 +1,225 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + + v1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1" +) + +// VClusterApplyConfiguration represents a declarative configuration of the VCluster type for use +// with apply. +type VClusterApplyConfiguration struct { + v1.TypeMetaApplyConfiguration `json:",inline"` + *v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"` + Spec *VClusterSpecApplyConfiguration `json:"spec,omitempty"` + Status *VClusterStatusApplyConfiguration `json:"status,omitempty"` +} + +// VCluster constructs a declarative configuration of the VCluster type for use with +// apply. +func VCluster(name string) *VClusterApplyConfiguration { + b := &VClusterApplyConfiguration{} + b.WithName(name) + b.WithKind("VCluster") + b.WithAPIVersion("mounts.contrib.kcp.io/v1alpha1") + return b +} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *VClusterApplyConfiguration) WithKind(value string) *VClusterApplyConfiguration { + b.Kind = &value + return b +} + +// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the APIVersion field is set to the value of the last call. +func (b *VClusterApplyConfiguration) WithAPIVersion(value string) *VClusterApplyConfiguration { + b.APIVersion = &value + return b +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *VClusterApplyConfiguration) WithName(value string) *VClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Name = &value + return b +} + +// WithGenerateName sets the GenerateName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the GenerateName field is set to the value of the last call. +func (b *VClusterApplyConfiguration) WithGenerateName(value string) *VClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.GenerateName = &value + return b +} + +// WithNamespace sets the Namespace field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Namespace field is set to the value of the last call. +func (b *VClusterApplyConfiguration) WithNamespace(value string) *VClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Namespace = &value + return b +} + +// WithUID sets the UID field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UID field is set to the value of the last call. +func (b *VClusterApplyConfiguration) WithUID(value types.UID) *VClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.UID = &value + return b +} + +// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ResourceVersion field is set to the value of the last call. +func (b *VClusterApplyConfiguration) WithResourceVersion(value string) *VClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ResourceVersion = &value + return b +} + +// WithGeneration sets the Generation field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Generation field is set to the value of the last call. +func (b *VClusterApplyConfiguration) WithGeneration(value int64) *VClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Generation = &value + return b +} + +// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the CreationTimestamp field is set to the value of the last call. +func (b *VClusterApplyConfiguration) WithCreationTimestamp(value metav1.Time) *VClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.CreationTimestamp = &value + return b +} + +// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionTimestamp field is set to the value of the last call. +func (b *VClusterApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *VClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.DeletionTimestamp = &value + return b +} + +// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call. +func (b *VClusterApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *VClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.DeletionGracePeriodSeconds = &value + return b +} + +// WithLabels puts the entries into the Labels field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Labels field, +// overwriting an existing map entries in Labels field with the same key. +func (b *VClusterApplyConfiguration) WithLabels(entries map[string]string) *VClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.Labels == nil && len(entries) > 0 { + b.Labels = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Labels[k] = v + } + return b +} + +// WithAnnotations puts the entries into the Annotations field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Annotations field, +// overwriting an existing map entries in Annotations field with the same key. +func (b *VClusterApplyConfiguration) WithAnnotations(entries map[string]string) *VClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.Annotations == nil && len(entries) > 0 { + b.Annotations = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Annotations[k] = v + } + return b +} + +// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the OwnerReferences field. +func (b *VClusterApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *VClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + if values[i] == nil { + panic("nil value passed to WithOwnerReferences") + } + b.OwnerReferences = append(b.OwnerReferences, *values[i]) + } + return b +} + +// WithFinalizers adds the given value to the Finalizers field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Finalizers field. +func (b *VClusterApplyConfiguration) WithFinalizers(values ...string) *VClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + b.Finalizers = append(b.Finalizers, values[i]) + } + return b +} + +func (b *VClusterApplyConfiguration) ensureObjectMetaApplyConfigurationExists() { + if b.ObjectMetaApplyConfiguration == nil { + b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{} + } +} + +// WithSpec sets the Spec field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Spec field is set to the value of the last call. +func (b *VClusterApplyConfiguration) WithSpec(value *VClusterSpecApplyConfiguration) *VClusterApplyConfiguration { + b.Spec = value + return b +} + +// WithStatus sets the Status field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Status field is set to the value of the last call. +func (b *VClusterApplyConfiguration) WithStatus(value *VClusterStatusApplyConfiguration) *VClusterApplyConfiguration { + b.Status = value + return b +} + +// GetName retrieves the value of the Name field in the declarative configuration. +func (b *VClusterApplyConfiguration) GetName() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.Name +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1/vclusterspec.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1/vclusterspec.go new file mode 100644 index 00000000000..c181adfce36 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1/vclusterspec.go @@ -0,0 +1,72 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "k8s.io/api/core/v1" + + v1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" +) + +// VClusterSpecApplyConfiguration represents a declarative configuration of the VClusterSpec type for use +// with apply. +type VClusterSpecApplyConfiguration struct { + Version *string `json:"version,omitempty"` + Mode *v1alpha1.KubeClusterMode `json:"mode,omitempty"` + SecretString *string `json:"secretString,omitempty"` + SecretRef *v1.ObjectReference `json:"secretRef,omitempty"` +} + +// VClusterSpecApplyConfiguration constructs a declarative configuration of the VClusterSpec type for use with +// apply. +func VClusterSpec() *VClusterSpecApplyConfiguration { + return &VClusterSpecApplyConfiguration{} +} + +// WithVersion sets the Version field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Version field is set to the value of the last call. +func (b *VClusterSpecApplyConfiguration) WithVersion(value string) *VClusterSpecApplyConfiguration { + b.Version = &value + return b +} + +// WithMode sets the Mode field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Mode field is set to the value of the last call. +func (b *VClusterSpecApplyConfiguration) WithMode(value v1alpha1.KubeClusterMode) *VClusterSpecApplyConfiguration { + b.Mode = &value + return b +} + +// WithSecretString sets the SecretString field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the SecretString field is set to the value of the last call. +func (b *VClusterSpecApplyConfiguration) WithSecretString(value string) *VClusterSpecApplyConfiguration { + b.SecretString = &value + return b +} + +// WithSecretRef sets the SecretRef field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the SecretRef field is set to the value of the last call. +func (b *VClusterSpecApplyConfiguration) WithSecretRef(value v1.ObjectReference) *VClusterSpecApplyConfiguration { + b.SecretRef = &value + return b +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1/vclusterstatus.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1/vclusterstatus.go new file mode 100644 index 00000000000..ab5ac840f1a --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1/vclusterstatus.go @@ -0,0 +1,82 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/kcp-dev/kcp/sdk/apis/tenancy/v1alpha1" + conditionsv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// VClusterStatusApplyConfiguration represents a declarative configuration of the VClusterStatus type for use +// with apply. +type VClusterStatusApplyConfiguration struct { + URL *string `json:"URL,omitempty"` + SecretString *string `json:"secretString,omitempty"` + Phase *v1alpha1.MountPhaseType `json:"phase,omitempty"` + LastProxyHeartbeatTime *v1.Time `json:"lastProxyHeartbeatTime,omitempty"` + Conditions *conditionsv1alpha1.Conditions `json:"conditions,omitempty"` +} + +// VClusterStatusApplyConfiguration constructs a declarative configuration of the VClusterStatus type for use with +// apply. +func VClusterStatus() *VClusterStatusApplyConfiguration { + return &VClusterStatusApplyConfiguration{} +} + +// WithURL sets the URL field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the URL field is set to the value of the last call. +func (b *VClusterStatusApplyConfiguration) WithURL(value string) *VClusterStatusApplyConfiguration { + b.URL = &value + return b +} + +// WithSecretString sets the SecretString field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the SecretString field is set to the value of the last call. +func (b *VClusterStatusApplyConfiguration) WithSecretString(value string) *VClusterStatusApplyConfiguration { + b.SecretString = &value + return b +} + +// WithPhase sets the Phase field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Phase field is set to the value of the last call. +func (b *VClusterStatusApplyConfiguration) WithPhase(value v1alpha1.MountPhaseType) *VClusterStatusApplyConfiguration { + b.Phase = &value + return b +} + +// WithLastProxyHeartbeatTime sets the LastProxyHeartbeatTime field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the LastProxyHeartbeatTime field is set to the value of the last call. +func (b *VClusterStatusApplyConfiguration) WithLastProxyHeartbeatTime(value v1.Time) *VClusterStatusApplyConfiguration { + b.LastProxyHeartbeatTime = &value + return b +} + +// WithConditions sets the Conditions field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Conditions field is set to the value of the last call. +func (b *VClusterStatusApplyConfiguration) WithConditions(value conditionsv1alpha1.Conditions) *VClusterStatusApplyConfiguration { + b.Conditions = &value + return b +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1/targetkubecluster.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1/targetkubecluster.go new file mode 100644 index 00000000000..59ad44fbf3d --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1/targetkubecluster.go @@ -0,0 +1,225 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + + v1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1" +) + +// TargetKubeClusterApplyConfiguration represents a declarative configuration of the TargetKubeCluster type for use +// with apply. +type TargetKubeClusterApplyConfiguration struct { + v1.TypeMetaApplyConfiguration `json:",inline"` + *v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"` + Spec *TargetKubeClusterSpecApplyConfiguration `json:"spec,omitempty"` + Status *TargetKubeClusterStatusApplyConfiguration `json:"status,omitempty"` +} + +// TargetKubeCluster constructs a declarative configuration of the TargetKubeCluster type for use with +// apply. +func TargetKubeCluster(name string) *TargetKubeClusterApplyConfiguration { + b := &TargetKubeClusterApplyConfiguration{} + b.WithName(name) + b.WithKind("TargetKubeCluster") + b.WithAPIVersion("targets.contrib.kcp.io/v1alpha1") + return b +} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *TargetKubeClusterApplyConfiguration) WithKind(value string) *TargetKubeClusterApplyConfiguration { + b.Kind = &value + return b +} + +// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the APIVersion field is set to the value of the last call. +func (b *TargetKubeClusterApplyConfiguration) WithAPIVersion(value string) *TargetKubeClusterApplyConfiguration { + b.APIVersion = &value + return b +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *TargetKubeClusterApplyConfiguration) WithName(value string) *TargetKubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Name = &value + return b +} + +// WithGenerateName sets the GenerateName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the GenerateName field is set to the value of the last call. +func (b *TargetKubeClusterApplyConfiguration) WithGenerateName(value string) *TargetKubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.GenerateName = &value + return b +} + +// WithNamespace sets the Namespace field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Namespace field is set to the value of the last call. +func (b *TargetKubeClusterApplyConfiguration) WithNamespace(value string) *TargetKubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Namespace = &value + return b +} + +// WithUID sets the UID field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UID field is set to the value of the last call. +func (b *TargetKubeClusterApplyConfiguration) WithUID(value types.UID) *TargetKubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.UID = &value + return b +} + +// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ResourceVersion field is set to the value of the last call. +func (b *TargetKubeClusterApplyConfiguration) WithResourceVersion(value string) *TargetKubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ResourceVersion = &value + return b +} + +// WithGeneration sets the Generation field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Generation field is set to the value of the last call. +func (b *TargetKubeClusterApplyConfiguration) WithGeneration(value int64) *TargetKubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Generation = &value + return b +} + +// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the CreationTimestamp field is set to the value of the last call. +func (b *TargetKubeClusterApplyConfiguration) WithCreationTimestamp(value metav1.Time) *TargetKubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.CreationTimestamp = &value + return b +} + +// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionTimestamp field is set to the value of the last call. +func (b *TargetKubeClusterApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *TargetKubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.DeletionTimestamp = &value + return b +} + +// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call. +func (b *TargetKubeClusterApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *TargetKubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.DeletionGracePeriodSeconds = &value + return b +} + +// WithLabels puts the entries into the Labels field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Labels field, +// overwriting an existing map entries in Labels field with the same key. +func (b *TargetKubeClusterApplyConfiguration) WithLabels(entries map[string]string) *TargetKubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.Labels == nil && len(entries) > 0 { + b.Labels = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Labels[k] = v + } + return b +} + +// WithAnnotations puts the entries into the Annotations field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Annotations field, +// overwriting an existing map entries in Annotations field with the same key. +func (b *TargetKubeClusterApplyConfiguration) WithAnnotations(entries map[string]string) *TargetKubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.Annotations == nil && len(entries) > 0 { + b.Annotations = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Annotations[k] = v + } + return b +} + +// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the OwnerReferences field. +func (b *TargetKubeClusterApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *TargetKubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + if values[i] == nil { + panic("nil value passed to WithOwnerReferences") + } + b.OwnerReferences = append(b.OwnerReferences, *values[i]) + } + return b +} + +// WithFinalizers adds the given value to the Finalizers field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Finalizers field. +func (b *TargetKubeClusterApplyConfiguration) WithFinalizers(values ...string) *TargetKubeClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + b.Finalizers = append(b.Finalizers, values[i]) + } + return b +} + +func (b *TargetKubeClusterApplyConfiguration) ensureObjectMetaApplyConfigurationExists() { + if b.ObjectMetaApplyConfiguration == nil { + b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{} + } +} + +// WithSpec sets the Spec field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Spec field is set to the value of the last call. +func (b *TargetKubeClusterApplyConfiguration) WithSpec(value *TargetKubeClusterSpecApplyConfiguration) *TargetKubeClusterApplyConfiguration { + b.Spec = value + return b +} + +// WithStatus sets the Status field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Status field is set to the value of the last call. +func (b *TargetKubeClusterApplyConfiguration) WithStatus(value *TargetKubeClusterStatusApplyConfiguration) *TargetKubeClusterApplyConfiguration { + b.Status = value + return b +} + +// GetName retrieves the value of the Name field in the declarative configuration. +func (b *TargetKubeClusterApplyConfiguration) GetName() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.Name +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1/targetkubeclusterspec.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1/targetkubeclusterspec.go new file mode 100644 index 00000000000..0b05f01e061 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1/targetkubeclusterspec.go @@ -0,0 +1,43 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "k8s.io/api/core/v1" +) + +// TargetKubeClusterSpecApplyConfiguration represents a declarative configuration of the TargetKubeClusterSpec type for use +// with apply. +type TargetKubeClusterSpecApplyConfiguration struct { + SecretRef *v1.ObjectReference `json:"secretRef,omitempty"` +} + +// TargetKubeClusterSpecApplyConfiguration constructs a declarative configuration of the TargetKubeClusterSpec type for use with +// apply. +func TargetKubeClusterSpec() *TargetKubeClusterSpecApplyConfiguration { + return &TargetKubeClusterSpecApplyConfiguration{} +} + +// WithSecretRef sets the SecretRef field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the SecretRef field is set to the value of the last call. +func (b *TargetKubeClusterSpecApplyConfiguration) WithSecretRef(value v1.ObjectReference) *TargetKubeClusterSpecApplyConfiguration { + b.SecretRef = &value + return b +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1/targetkubeclusterstatus.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1/targetkubeclusterstatus.go new file mode 100644 index 00000000000..2879c453438 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1/targetkubeclusterstatus.go @@ -0,0 +1,82 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/kcp-dev/kcp/sdk/apis/tenancy/v1alpha1" + conditionsv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// TargetKubeClusterStatusApplyConfiguration represents a declarative configuration of the TargetKubeClusterStatus type for use +// with apply. +type TargetKubeClusterStatusApplyConfiguration struct { + Phase *v1alpha1.MountPhaseType `json:"phase,omitempty"` + LastProxyHeartbeatTime *v1.Time `json:"lastProxyHeartbeatTime,omitempty"` + Conditions *conditionsv1alpha1.Conditions `json:"conditions,omitempty"` + SecretString *string `json:"secretString,omitempty"` + URL *string `json:"URL,omitempty"` +} + +// TargetKubeClusterStatusApplyConfiguration constructs a declarative configuration of the TargetKubeClusterStatus type for use with +// apply. +func TargetKubeClusterStatus() *TargetKubeClusterStatusApplyConfiguration { + return &TargetKubeClusterStatusApplyConfiguration{} +} + +// WithPhase sets the Phase field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Phase field is set to the value of the last call. +func (b *TargetKubeClusterStatusApplyConfiguration) WithPhase(value v1alpha1.MountPhaseType) *TargetKubeClusterStatusApplyConfiguration { + b.Phase = &value + return b +} + +// WithLastProxyHeartbeatTime sets the LastProxyHeartbeatTime field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the LastProxyHeartbeatTime field is set to the value of the last call. +func (b *TargetKubeClusterStatusApplyConfiguration) WithLastProxyHeartbeatTime(value v1.Time) *TargetKubeClusterStatusApplyConfiguration { + b.LastProxyHeartbeatTime = &value + return b +} + +// WithConditions sets the Conditions field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Conditions field is set to the value of the last call. +func (b *TargetKubeClusterStatusApplyConfiguration) WithConditions(value conditionsv1alpha1.Conditions) *TargetKubeClusterStatusApplyConfiguration { + b.Conditions = &value + return b +} + +// WithSecretString sets the SecretString field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the SecretString field is set to the value of the last call. +func (b *TargetKubeClusterStatusApplyConfiguration) WithSecretString(value string) *TargetKubeClusterStatusApplyConfiguration { + b.SecretString = &value + return b +} + +// WithURL sets the URL field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the URL field is set to the value of the last call. +func (b *TargetKubeClusterStatusApplyConfiguration) WithURL(value string) *TargetKubeClusterStatusApplyConfiguration { + b.URL = &value + return b +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1/targetvcluster.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1/targetvcluster.go new file mode 100644 index 00000000000..a3afc6118d9 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1/targetvcluster.go @@ -0,0 +1,225 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + + v1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1" +) + +// TargetVClusterApplyConfiguration represents a declarative configuration of the TargetVCluster type for use +// with apply. +type TargetVClusterApplyConfiguration struct { + v1.TypeMetaApplyConfiguration `json:",inline"` + *v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"` + Spec *TargetVClusterSpecApplyConfiguration `json:"spec,omitempty"` + Status *TargetVClusterStatusApplyConfiguration `json:"status,omitempty"` +} + +// TargetVCluster constructs a declarative configuration of the TargetVCluster type for use with +// apply. +func TargetVCluster(name string) *TargetVClusterApplyConfiguration { + b := &TargetVClusterApplyConfiguration{} + b.WithName(name) + b.WithKind("TargetVCluster") + b.WithAPIVersion("targets.contrib.kcp.io/v1alpha1") + return b +} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *TargetVClusterApplyConfiguration) WithKind(value string) *TargetVClusterApplyConfiguration { + b.Kind = &value + return b +} + +// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the APIVersion field is set to the value of the last call. +func (b *TargetVClusterApplyConfiguration) WithAPIVersion(value string) *TargetVClusterApplyConfiguration { + b.APIVersion = &value + return b +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *TargetVClusterApplyConfiguration) WithName(value string) *TargetVClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Name = &value + return b +} + +// WithGenerateName sets the GenerateName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the GenerateName field is set to the value of the last call. +func (b *TargetVClusterApplyConfiguration) WithGenerateName(value string) *TargetVClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.GenerateName = &value + return b +} + +// WithNamespace sets the Namespace field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Namespace field is set to the value of the last call. +func (b *TargetVClusterApplyConfiguration) WithNamespace(value string) *TargetVClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Namespace = &value + return b +} + +// WithUID sets the UID field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UID field is set to the value of the last call. +func (b *TargetVClusterApplyConfiguration) WithUID(value types.UID) *TargetVClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.UID = &value + return b +} + +// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ResourceVersion field is set to the value of the last call. +func (b *TargetVClusterApplyConfiguration) WithResourceVersion(value string) *TargetVClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ResourceVersion = &value + return b +} + +// WithGeneration sets the Generation field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Generation field is set to the value of the last call. +func (b *TargetVClusterApplyConfiguration) WithGeneration(value int64) *TargetVClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.Generation = &value + return b +} + +// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the CreationTimestamp field is set to the value of the last call. +func (b *TargetVClusterApplyConfiguration) WithCreationTimestamp(value metav1.Time) *TargetVClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.CreationTimestamp = &value + return b +} + +// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionTimestamp field is set to the value of the last call. +func (b *TargetVClusterApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *TargetVClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.DeletionTimestamp = &value + return b +} + +// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call. +func (b *TargetVClusterApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *TargetVClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.DeletionGracePeriodSeconds = &value + return b +} + +// WithLabels puts the entries into the Labels field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Labels field, +// overwriting an existing map entries in Labels field with the same key. +func (b *TargetVClusterApplyConfiguration) WithLabels(entries map[string]string) *TargetVClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.Labels == nil && len(entries) > 0 { + b.Labels = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Labels[k] = v + } + return b +} + +// WithAnnotations puts the entries into the Annotations field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Annotations field, +// overwriting an existing map entries in Annotations field with the same key. +func (b *TargetVClusterApplyConfiguration) WithAnnotations(entries map[string]string) *TargetVClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.Annotations == nil && len(entries) > 0 { + b.Annotations = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.Annotations[k] = v + } + return b +} + +// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the OwnerReferences field. +func (b *TargetVClusterApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *TargetVClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + if values[i] == nil { + panic("nil value passed to WithOwnerReferences") + } + b.OwnerReferences = append(b.OwnerReferences, *values[i]) + } + return b +} + +// WithFinalizers adds the given value to the Finalizers field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Finalizers field. +func (b *TargetVClusterApplyConfiguration) WithFinalizers(values ...string) *TargetVClusterApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + b.Finalizers = append(b.Finalizers, values[i]) + } + return b +} + +func (b *TargetVClusterApplyConfiguration) ensureObjectMetaApplyConfigurationExists() { + if b.ObjectMetaApplyConfiguration == nil { + b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{} + } +} + +// WithSpec sets the Spec field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Spec field is set to the value of the last call. +func (b *TargetVClusterApplyConfiguration) WithSpec(value *TargetVClusterSpecApplyConfiguration) *TargetVClusterApplyConfiguration { + b.Spec = value + return b +} + +// WithStatus sets the Status field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Status field is set to the value of the last call. +func (b *TargetVClusterApplyConfiguration) WithStatus(value *TargetVClusterStatusApplyConfiguration) *TargetVClusterApplyConfiguration { + b.Status = value + return b +} + +// GetName retrieves the value of the Name field in the declarative configuration. +func (b *TargetVClusterApplyConfiguration) GetName() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.Name +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1/targetvclusterspec.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1/targetvclusterspec.go new file mode 100644 index 00000000000..c8d23f988f2 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1/targetvclusterspec.go @@ -0,0 +1,43 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "k8s.io/api/core/v1" +) + +// TargetVClusterSpecApplyConfiguration represents a declarative configuration of the TargetVClusterSpec type for use +// with apply. +type TargetVClusterSpecApplyConfiguration struct { + SecretRef *v1.ObjectReference `json:"secretRef,omitempty"` +} + +// TargetVClusterSpecApplyConfiguration constructs a declarative configuration of the TargetVClusterSpec type for use with +// apply. +func TargetVClusterSpec() *TargetVClusterSpecApplyConfiguration { + return &TargetVClusterSpecApplyConfiguration{} +} + +// WithSecretRef sets the SecretRef field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the SecretRef field is set to the value of the last call. +func (b *TargetVClusterSpecApplyConfiguration) WithSecretRef(value v1.ObjectReference) *TargetVClusterSpecApplyConfiguration { + b.SecretRef = &value + return b +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1/targetvclusterstatus.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1/targetvclusterstatus.go new file mode 100644 index 00000000000..09e6a97109b --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1/targetvclusterstatus.go @@ -0,0 +1,82 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/kcp-dev/kcp/sdk/apis/tenancy/v1alpha1" + conditionsv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// TargetVClusterStatusApplyConfiguration represents a declarative configuration of the TargetVClusterStatus type for use +// with apply. +type TargetVClusterStatusApplyConfiguration struct { + Phase *v1alpha1.MountPhaseType `json:"phase,omitempty"` + LastProxyHeartbeatTime *v1.Time `json:"lastProxyHeartbeatTime,omitempty"` + Conditions *conditionsv1alpha1.Conditions `json:"conditions,omitempty"` + SecretString *string `json:"secretString,omitempty"` + URL *string `json:"URL,omitempty"` +} + +// TargetVClusterStatusApplyConfiguration constructs a declarative configuration of the TargetVClusterStatus type for use with +// apply. +func TargetVClusterStatus() *TargetVClusterStatusApplyConfiguration { + return &TargetVClusterStatusApplyConfiguration{} +} + +// WithPhase sets the Phase field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Phase field is set to the value of the last call. +func (b *TargetVClusterStatusApplyConfiguration) WithPhase(value v1alpha1.MountPhaseType) *TargetVClusterStatusApplyConfiguration { + b.Phase = &value + return b +} + +// WithLastProxyHeartbeatTime sets the LastProxyHeartbeatTime field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the LastProxyHeartbeatTime field is set to the value of the last call. +func (b *TargetVClusterStatusApplyConfiguration) WithLastProxyHeartbeatTime(value v1.Time) *TargetVClusterStatusApplyConfiguration { + b.LastProxyHeartbeatTime = &value + return b +} + +// WithConditions sets the Conditions field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Conditions field is set to the value of the last call. +func (b *TargetVClusterStatusApplyConfiguration) WithConditions(value conditionsv1alpha1.Conditions) *TargetVClusterStatusApplyConfiguration { + b.Conditions = &value + return b +} + +// WithSecretString sets the SecretString field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the SecretString field is set to the value of the last call. +func (b *TargetVClusterStatusApplyConfiguration) WithSecretString(value string) *TargetVClusterStatusApplyConfiguration { + b.SecretString = &value + return b +} + +// WithURL sets the URL field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the URL field is set to the value of the last call. +func (b *TargetVClusterStatusApplyConfiguration) WithURL(value string) *TargetVClusterStatusApplyConfiguration { + b.URL = &value + return b +} diff --git a/contrib/mounts-virtualworkspace/client/applyconfiguration/utils.go b/contrib/mounts-virtualworkspace/client/applyconfiguration/utils.go new file mode 100644 index 00000000000..c348d047abc --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/applyconfiguration/utils.go @@ -0,0 +1,99 @@ +/* +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 applyconfiguration-gen. DO NOT EDIT. + +package applyconfiguration + +import ( + v1alpha1 "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + metav1 "k8s.io/client-go/applyconfigurations/meta/v1" + testing "k8s.io/client-go/testing" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" + conditionsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/conditions/v1alpha1" + internal "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/internal" + applyconfigurationmetav1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/meta/v1" + applyconfigurationmountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1" + applyconfigurationtargetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1" +) + +// ForKind returns an apply configuration type for the given GroupVersionKind, or nil if no +// apply configuration type exists for the given GroupVersionKind. +func ForKind(kind schema.GroupVersionKind) interface{} { + switch kind { + // Group=conditions, Version=v1alpha1 + case v1alpha1.SchemeGroupVersion.WithKind("Condition"): + return &conditionsv1alpha1.ConditionApplyConfiguration{} + + // Group=meta.k8s.io, Version=v1 + case v1.SchemeGroupVersion.WithKind("Condition"): + return &metav1.ConditionApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("DeleteOptions"): + return &metav1.DeleteOptionsApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("LabelSelector"): + return &metav1.LabelSelectorApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("LabelSelectorRequirement"): + return &metav1.LabelSelectorRequirementApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("ManagedFieldsEntry"): + return &applyconfigurationmetav1.ManagedFieldsEntryApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("ObjectMeta"): + return &applyconfigurationmetav1.ObjectMetaApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("OwnerReference"): + return &applyconfigurationmetav1.OwnerReferenceApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("TypeMeta"): + return &applyconfigurationmetav1.TypeMetaApplyConfiguration{} + + // Group=mounts.contrib.kcp.io, Version=v1alpha1 + case mountsv1alpha1.SchemeGroupVersion.WithKind("KubeCluster"): + return &applyconfigurationmountsv1alpha1.KubeClusterApplyConfiguration{} + case mountsv1alpha1.SchemeGroupVersion.WithKind("KubeClusterSpec"): + return &applyconfigurationmountsv1alpha1.KubeClusterSpecApplyConfiguration{} + case mountsv1alpha1.SchemeGroupVersion.WithKind("KubeClusterStatus"): + return &applyconfigurationmountsv1alpha1.KubeClusterStatusApplyConfiguration{} + case mountsv1alpha1.SchemeGroupVersion.WithKind("VCluster"): + return &applyconfigurationmountsv1alpha1.VClusterApplyConfiguration{} + case mountsv1alpha1.SchemeGroupVersion.WithKind("VClusterSpec"): + return &applyconfigurationmountsv1alpha1.VClusterSpecApplyConfiguration{} + case mountsv1alpha1.SchemeGroupVersion.WithKind("VClusterStatus"): + return &applyconfigurationmountsv1alpha1.VClusterStatusApplyConfiguration{} + + // Group=targets.contrib.kcp.io, Version=v1alpha1 + case targetsv1alpha1.SchemeGroupVersion.WithKind("TargetKubeCluster"): + return &applyconfigurationtargetsv1alpha1.TargetKubeClusterApplyConfiguration{} + case targetsv1alpha1.SchemeGroupVersion.WithKind("TargetKubeClusterSpec"): + return &applyconfigurationtargetsv1alpha1.TargetKubeClusterSpecApplyConfiguration{} + case targetsv1alpha1.SchemeGroupVersion.WithKind("TargetKubeClusterStatus"): + return &applyconfigurationtargetsv1alpha1.TargetKubeClusterStatusApplyConfiguration{} + case targetsv1alpha1.SchemeGroupVersion.WithKind("TargetVCluster"): + return &applyconfigurationtargetsv1alpha1.TargetVClusterApplyConfiguration{} + case targetsv1alpha1.SchemeGroupVersion.WithKind("TargetVClusterSpec"): + return &applyconfigurationtargetsv1alpha1.TargetVClusterSpecApplyConfiguration{} + case targetsv1alpha1.SchemeGroupVersion.WithKind("TargetVClusterStatus"): + return &applyconfigurationtargetsv1alpha1.TargetVClusterStatusApplyConfiguration{} + + } + return nil +} + +func NewTypeConverter(scheme *runtime.Scheme) *testing.TypeConverter { + return &testing.TypeConverter{Scheme: scheme, TypeResolver: internal.Parser()} +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/clientset.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/clientset.go new file mode 100644 index 00000000000..e28fa7a5b94 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/clientset.go @@ -0,0 +1,134 @@ +/* +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 versioned + +import ( + "fmt" + "net/http" + + discovery "k8s.io/client-go/discovery" + rest "k8s.io/client-go/rest" + flowcontrol "k8s.io/client-go/util/flowcontrol" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1" + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1" +) + +type Interface interface { + Discovery() discovery.DiscoveryInterface + MountsV1alpha1() mountsv1alpha1.MountsV1alpha1Interface + TargetsV1alpha1() targetsv1alpha1.TargetsV1alpha1Interface +} + +// Clientset contains the clients for groups. +type Clientset struct { + *discovery.DiscoveryClient + mountsV1alpha1 *mountsv1alpha1.MountsV1alpha1Client + targetsV1alpha1 *targetsv1alpha1.TargetsV1alpha1Client +} + +// MountsV1alpha1 retrieves the MountsV1alpha1Client +func (c *Clientset) MountsV1alpha1() mountsv1alpha1.MountsV1alpha1Interface { + return c.mountsV1alpha1 +} + +// TargetsV1alpha1 retrieves the TargetsV1alpha1Client +func (c *Clientset) TargetsV1alpha1() targetsv1alpha1.TargetsV1alpha1Interface { + return c.targetsV1alpha1 +} + +// Discovery retrieves the DiscoveryClient +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + if c == nil { + return nil + } + return c.DiscoveryClient +} + +// NewForConfig creates a new Clientset for the given config. +// If config's RateLimiter is not set and QPS and Burst are acceptable, +// NewForConfig will generate a rate-limiter in configShallowCopy. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*Clientset, error) { + configShallowCopy := *c + + if configShallowCopy.UserAgent == "" { + configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent() + } + + // share the transport between all clients + httpClient, err := rest.HTTPClientFor(&configShallowCopy) + if err != nil { + return nil, err + } + + return NewForConfigAndClient(&configShallowCopy, httpClient) +} + +// NewForConfigAndClient creates a new Clientset for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +// If config's RateLimiter is not set and QPS and Burst are acceptable, +// NewForConfigAndClient will generate a rate-limiter in configShallowCopy. +func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error) { + configShallowCopy := *c + if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { + if configShallowCopy.Burst <= 0 { + return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0") + } + configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) + } + + var cs Clientset + var err error + cs.mountsV1alpha1, err = mountsv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } + cs.targetsV1alpha1, err = targetsv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } + + cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } + return &cs, nil +} + +// NewForConfigOrDie creates a new Clientset for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *Clientset { + cs, err := NewForConfig(c) + if err != nil { + panic(err) + } + return cs +} + +// New creates a new Clientset for the given RESTClient. +func New(c rest.Interface) *Clientset { + var cs Clientset + cs.mountsV1alpha1 = mountsv1alpha1.New(c) + cs.targetsV1alpha1 = targetsv1alpha1.New(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClient(c) + return &cs +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/clientset.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/clientset.go new file mode 100644 index 00000000000..0c332649239 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/clientset.go @@ -0,0 +1,149 @@ +//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 clientset + +import ( + "fmt" + "net/http" + + kcpclient "github.com/kcp-dev/apimachinery/v2/pkg/client" + "github.com/kcp-dev/logicalcluster/v3" + + "k8s.io/client-go/discovery" + "k8s.io/client-go/rest" + "k8s.io/client-go/util/flowcontrol" + + client "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned" + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1" + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1" +) + +type ClusterInterface interface { + Cluster(logicalcluster.Path) client.Interface + Discovery() discovery.DiscoveryInterface + MountsV1alpha1() mountsv1alpha1.MountsV1alpha1ClusterInterface + TargetsV1alpha1() targetsv1alpha1.TargetsV1alpha1ClusterInterface +} + +// ClusterClientset contains the clients for groups. +type ClusterClientset struct { + *discovery.DiscoveryClient + clientCache kcpclient.Cache[*client.Clientset] + mountsV1alpha1 *mountsv1alpha1.MountsV1alpha1ClusterClient + targetsV1alpha1 *targetsv1alpha1.TargetsV1alpha1ClusterClient +} + +// Discovery retrieves the DiscoveryClient +func (c *ClusterClientset) Discovery() discovery.DiscoveryInterface { + if c == nil { + return nil + } + return c.DiscoveryClient +} + +// MountsV1alpha1 retrieves the MountsV1alpha1ClusterClient. +func (c *ClusterClientset) MountsV1alpha1() mountsv1alpha1.MountsV1alpha1ClusterInterface { + return c.mountsV1alpha1 +} + +// TargetsV1alpha1 retrieves the TargetsV1alpha1ClusterClient. +func (c *ClusterClientset) TargetsV1alpha1() targetsv1alpha1.TargetsV1alpha1ClusterInterface { + return c.targetsV1alpha1 +} + +// Cluster scopes this clientset to one cluster. +func (c *ClusterClientset) Cluster(clusterPath logicalcluster.Path) client.Interface { + if clusterPath == logicalcluster.Wildcard { + panic("A specific cluster must be provided when scoping, not the wildcard.") + } + return c.clientCache.ClusterOrDie(clusterPath) +} + +// NewForConfig creates a new ClusterClientset for the given config. +// If config's RateLimiter is not set and QPS and Burst are acceptable, +// NewForConfig will generate a rate-limiter in configShallowCopy. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*ClusterClientset, error) { + configShallowCopy := *c + + if configShallowCopy.UserAgent == "" { + configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent() + } + + // share the transport between all clients + httpClient, err := rest.HTTPClientFor(&configShallowCopy) + if err != nil { + return nil, err + } + + return NewForConfigAndClient(&configShallowCopy, httpClient) +} + +// NewForConfigAndClient creates a new ClusterClientset for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +// If config's RateLimiter is not set and QPS and Burst are acceptable, +// NewForConfigAndClient will generate a rate-limiter in configShallowCopy. +func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*ClusterClientset, error) { + configShallowCopy := *c + if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { + if configShallowCopy.Burst <= 0 { + return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0") + } + configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) + } + + cache := kcpclient.NewCache(c, httpClient, &kcpclient.Constructor[*client.Clientset]{ + NewForConfigAndClient: client.NewForConfigAndClient, + }) + if _, err := cache.Cluster(logicalcluster.Name("root").Path()); err != nil { + return nil, err + } + + var cs ClusterClientset + cs.clientCache = cache + var err error + cs.mountsV1alpha1, err = mountsv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } + cs.targetsV1alpha1, err = targetsv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } + + cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } + return &cs, nil +} + +// NewForConfigOrDie creates a new ClusterClientset for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *ClusterClientset { + cs, err := NewForConfig(c) + if err != nil { + panic(err) + } + return cs +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/fake/clientset.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/fake/clientset.go new file mode 100644 index 00000000000..d8396fd0cc4 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/fake/clientset.go @@ -0,0 +1,127 @@ +//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 fake + +import ( + "github.com/kcp-dev/logicalcluster/v3" + + kcpfakediscovery "github.com/kcp-dev/client-go/third_party/k8s.io/client-go/discovery/fake" + kcptesting "github.com/kcp-dev/client-go/third_party/k8s.io/client-go/testing" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/discovery" + + client "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned" + kcpclient "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster" + kcpmountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1" + fakemountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1/fake" + kcptargetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1" + faketargetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1/fake" + clientscheme "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/scheme" + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1" + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1" +) + +// NewSimpleClientset returns a clientset that will respond with the provided objects. +// It's backed by a very simple object tracker that processes creates, updates and deletions as-is, +// without applying any validations and/or defaults. It shouldn't be considered a replacement +// for a real clientset and is mostly useful in simple unit tests. +func NewSimpleClientset(objects ...runtime.Object) *ClusterClientset { + o := kcptesting.NewObjectTracker(clientscheme.Scheme, clientscheme.Codecs.UniversalDecoder()) + o.AddAll(objects...) + + cs := &ClusterClientset{Fake: &kcptesting.Fake{}, tracker: o} + cs.discovery = &kcpfakediscovery.FakeDiscovery{Fake: cs.Fake, ClusterPath: logicalcluster.Wildcard} + cs.AddReactor("*", "*", kcptesting.ObjectReaction(o)) + cs.AddWatchReactor("*", kcptesting.WatchReaction(o)) + + return cs +} + +var _ kcpclient.ClusterInterface = (*ClusterClientset)(nil) + +// ClusterClientset contains the clients for groups. +type ClusterClientset struct { + *kcptesting.Fake + discovery *kcpfakediscovery.FakeDiscovery + tracker kcptesting.ObjectTracker +} + +// Discovery retrieves the DiscoveryClient +func (c *ClusterClientset) Discovery() discovery.DiscoveryInterface { + return c.discovery +} + +func (c *ClusterClientset) Tracker() kcptesting.ObjectTracker { + return c.tracker +} + +// MountsV1alpha1 retrieves the MountsV1alpha1ClusterClient. +func (c *ClusterClientset) MountsV1alpha1() kcpmountsv1alpha1.MountsV1alpha1ClusterInterface { + return &fakemountsv1alpha1.MountsV1alpha1ClusterClient{Fake: c.Fake} +} + +// TargetsV1alpha1 retrieves the TargetsV1alpha1ClusterClient. +func (c *ClusterClientset) TargetsV1alpha1() kcptargetsv1alpha1.TargetsV1alpha1ClusterInterface { + return &faketargetsv1alpha1.TargetsV1alpha1ClusterClient{Fake: c.Fake} +} + +// Cluster scopes this clientset to one cluster. +func (c *ClusterClientset) Cluster(clusterPath logicalcluster.Path) client.Interface { + if clusterPath == logicalcluster.Wildcard { + panic("A specific cluster must be provided when scoping, not the wildcard.") + } + return &Clientset{ + Fake: c.Fake, + discovery: &kcpfakediscovery.FakeDiscovery{Fake: c.Fake, ClusterPath: clusterPath}, + tracker: c.tracker.Cluster(clusterPath), + clusterPath: clusterPath, + } +} + +var _ client.Interface = (*Clientset)(nil) + +// Clientset contains the clients for groups. +type Clientset struct { + *kcptesting.Fake + discovery *kcpfakediscovery.FakeDiscovery + tracker kcptesting.ScopedObjectTracker + clusterPath logicalcluster.Path +} + +// Discovery retrieves the DiscoveryClient +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + return c.discovery +} + +func (c *Clientset) Tracker() kcptesting.ScopedObjectTracker { + return c.tracker +} + +// MountsV1alpha1 retrieves the MountsV1alpha1Client. +func (c *Clientset) MountsV1alpha1() mountsv1alpha1.MountsV1alpha1Interface { + return &fakemountsv1alpha1.MountsV1alpha1Client{Fake: c.Fake, ClusterPath: c.clusterPath} +} + +// TargetsV1alpha1 retrieves the TargetsV1alpha1Client. +func (c *Clientset) TargetsV1alpha1() targetsv1alpha1.TargetsV1alpha1Interface { + return &faketargetsv1alpha1.TargetsV1alpha1Client{Fake: c.Fake, ClusterPath: c.clusterPath} +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/scheme/register.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/scheme/register.go new file mode 100644 index 00000000000..8646f7f2114 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/scheme/register.go @@ -0,0 +1,62 @@ +//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 scheme + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" +) + +var Scheme = runtime.NewScheme() +var Codecs = serializer.NewCodecFactory(Scheme) +var ParameterCodec = runtime.NewParameterCodec(Scheme) +var localSchemeBuilder = runtime.SchemeBuilder{ + mountsv1alpha1.AddToScheme, + targetsv1alpha1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + metav1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(Scheme)) +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1/fake/kubecluster.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1/fake/kubecluster.go new file mode 100644 index 00000000000..bb953d9908a --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1/fake/kubecluster.go @@ -0,0 +1,202 @@ +//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 fake + +import ( + "context" + "encoding/json" + "fmt" + + "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" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + applyconfigurationsmountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1" + mountsv1alpha1client "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1" +) + +var kubeClustersResource = schema.GroupVersionResource{Group: "mounts.contrib.kcp.io", Version: "v1alpha1", Resource: "kubeclusters"} +var kubeClustersKind = schema.GroupVersionKind{Group: "mounts.contrib.kcp.io", Version: "v1alpha1", Kind: "KubeCluster"} + +type kubeClustersClusterClient struct { + *kcptesting.Fake +} + +// Cluster scopes the client down to a particular cluster. +func (c *kubeClustersClusterClient) Cluster(clusterPath logicalcluster.Path) mountsv1alpha1client.KubeClusterInterface { + if clusterPath == logicalcluster.Wildcard { + panic("A specific cluster must be provided when scoping, not the wildcard.") + } + + return &kubeClustersClient{Fake: c.Fake, ClusterPath: clusterPath} +} + +// List takes label and field selectors, and returns the list of KubeClusters that match those selectors across all clusters. +func (c *kubeClustersClusterClient) List(ctx context.Context, opts metav1.ListOptions) (*mountsv1alpha1.KubeClusterList, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootListAction(kubeClustersResource, kubeClustersKind, logicalcluster.Wildcard, opts), &mountsv1alpha1.KubeClusterList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &mountsv1alpha1.KubeClusterList{ListMeta: obj.(*mountsv1alpha1.KubeClusterList).ListMeta} + for _, item := range obj.(*mountsv1alpha1.KubeClusterList).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 KubeClusters across all clusters. +func (c *kubeClustersClusterClient) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(kcptesting.NewRootWatchAction(kubeClustersResource, logicalcluster.Wildcard, opts)) +} + +type kubeClustersClient struct { + *kcptesting.Fake + ClusterPath logicalcluster.Path +} + +func (c *kubeClustersClient) Create(ctx context.Context, kubeCluster *mountsv1alpha1.KubeCluster, opts metav1.CreateOptions) (*mountsv1alpha1.KubeCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootCreateAction(kubeClustersResource, c.ClusterPath, kubeCluster), &mountsv1alpha1.KubeCluster{}) + if obj == nil { + return nil, err + } + return obj.(*mountsv1alpha1.KubeCluster), err +} + +func (c *kubeClustersClient) Update(ctx context.Context, kubeCluster *mountsv1alpha1.KubeCluster, opts metav1.UpdateOptions) (*mountsv1alpha1.KubeCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootUpdateAction(kubeClustersResource, c.ClusterPath, kubeCluster), &mountsv1alpha1.KubeCluster{}) + if obj == nil { + return nil, err + } + return obj.(*mountsv1alpha1.KubeCluster), err +} + +func (c *kubeClustersClient) UpdateStatus(ctx context.Context, kubeCluster *mountsv1alpha1.KubeCluster, opts metav1.UpdateOptions) (*mountsv1alpha1.KubeCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootUpdateSubresourceAction(kubeClustersResource, c.ClusterPath, "status", kubeCluster), &mountsv1alpha1.KubeCluster{}) + if obj == nil { + return nil, err + } + return obj.(*mountsv1alpha1.KubeCluster), err +} + +func (c *kubeClustersClient) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + _, err := c.Fake.Invokes(kcptesting.NewRootDeleteActionWithOptions(kubeClustersResource, c.ClusterPath, name, opts), &mountsv1alpha1.KubeCluster{}) + return err +} + +func (c *kubeClustersClient) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + action := kcptesting.NewRootDeleteCollectionAction(kubeClustersResource, c.ClusterPath, listOpts) + + _, err := c.Fake.Invokes(action, &mountsv1alpha1.KubeClusterList{}) + return err +} + +func (c *kubeClustersClient) Get(ctx context.Context, name string, options metav1.GetOptions) (*mountsv1alpha1.KubeCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootGetAction(kubeClustersResource, c.ClusterPath, name), &mountsv1alpha1.KubeCluster{}) + if obj == nil { + return nil, err + } + return obj.(*mountsv1alpha1.KubeCluster), err +} + +// List takes label and field selectors, and returns the list of KubeClusters that match those selectors. +func (c *kubeClustersClient) List(ctx context.Context, opts metav1.ListOptions) (*mountsv1alpha1.KubeClusterList, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootListAction(kubeClustersResource, kubeClustersKind, c.ClusterPath, opts), &mountsv1alpha1.KubeClusterList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &mountsv1alpha1.KubeClusterList{ListMeta: obj.(*mountsv1alpha1.KubeClusterList).ListMeta} + for _, item := range obj.(*mountsv1alpha1.KubeClusterList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +func (c *kubeClustersClient) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(kcptesting.NewRootWatchAction(kubeClustersResource, c.ClusterPath, opts)) +} + +func (c *kubeClustersClient) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (*mountsv1alpha1.KubeCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootPatchSubresourceAction(kubeClustersResource, c.ClusterPath, name, pt, data, subresources...), &mountsv1alpha1.KubeCluster{}) + if obj == nil { + return nil, err + } + return obj.(*mountsv1alpha1.KubeCluster), err +} + +func (c *kubeClustersClient) Apply(ctx context.Context, applyConfiguration *applyconfigurationsmountsv1alpha1.KubeClusterApplyConfiguration, opts metav1.ApplyOptions) (*mountsv1alpha1.KubeCluster, error) { + if applyConfiguration == nil { + return nil, fmt.Errorf("applyConfiguration provided to Apply must not be nil") + } + data, err := json.Marshal(applyConfiguration) + if err != nil { + return nil, err + } + name := applyConfiguration.Name + if name == nil { + return nil, fmt.Errorf("applyConfiguration.Name must be provided to Apply") + } + obj, err := c.Fake.Invokes(kcptesting.NewRootPatchSubresourceAction(kubeClustersResource, c.ClusterPath, *name, types.ApplyPatchType, data), &mountsv1alpha1.KubeCluster{}) + if obj == nil { + return nil, err + } + return obj.(*mountsv1alpha1.KubeCluster), err +} + +func (c *kubeClustersClient) ApplyStatus(ctx context.Context, applyConfiguration *applyconfigurationsmountsv1alpha1.KubeClusterApplyConfiguration, opts metav1.ApplyOptions) (*mountsv1alpha1.KubeCluster, error) { + if applyConfiguration == nil { + return nil, fmt.Errorf("applyConfiguration provided to Apply must not be nil") + } + data, err := json.Marshal(applyConfiguration) + if err != nil { + return nil, err + } + name := applyConfiguration.Name + if name == nil { + return nil, fmt.Errorf("applyConfiguration.Name must be provided to Apply") + } + obj, err := c.Fake.Invokes(kcptesting.NewRootPatchSubresourceAction(kubeClustersResource, c.ClusterPath, *name, types.ApplyPatchType, data, "status"), &mountsv1alpha1.KubeCluster{}) + if obj == nil { + return nil, err + } + return obj.(*mountsv1alpha1.KubeCluster), err +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1/fake/mounts_client.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1/fake/mounts_client.go new file mode 100644 index 00000000000..bc90af24265 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1/fake/mounts_client.go @@ -0,0 +1,73 @@ +//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 fake + +import ( + "github.com/kcp-dev/logicalcluster/v3" + + kcptesting "github.com/kcp-dev/client-go/third_party/k8s.io/client-go/testing" + "k8s.io/client-go/rest" + + kcpmountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1" + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1" +) + +var _ kcpmountsv1alpha1.MountsV1alpha1ClusterInterface = (*MountsV1alpha1ClusterClient)(nil) + +type MountsV1alpha1ClusterClient struct { + *kcptesting.Fake +} + +func (c *MountsV1alpha1ClusterClient) Cluster(clusterPath logicalcluster.Path) mountsv1alpha1.MountsV1alpha1Interface { + if clusterPath == logicalcluster.Wildcard { + panic("A specific cluster must be provided when scoping, not the wildcard.") + } + return &MountsV1alpha1Client{Fake: c.Fake, ClusterPath: clusterPath} +} + +func (c *MountsV1alpha1ClusterClient) KubeClusters() kcpmountsv1alpha1.KubeClusterClusterInterface { + return &kubeClustersClusterClient{Fake: c.Fake} +} + +func (c *MountsV1alpha1ClusterClient) VClusters() kcpmountsv1alpha1.VClusterClusterInterface { + return &vClustersClusterClient{Fake: c.Fake} +} + +var _ mountsv1alpha1.MountsV1alpha1Interface = (*MountsV1alpha1Client)(nil) + +type MountsV1alpha1Client struct { + *kcptesting.Fake + ClusterPath logicalcluster.Path +} + +func (c *MountsV1alpha1Client) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} + +func (c *MountsV1alpha1Client) KubeClusters() mountsv1alpha1.KubeClusterInterface { + return &kubeClustersClient{Fake: c.Fake, ClusterPath: c.ClusterPath} +} + +func (c *MountsV1alpha1Client) VClusters() mountsv1alpha1.VClusterInterface { + return &vClustersClient{Fake: c.Fake, ClusterPath: c.ClusterPath} +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1/fake/vcluster.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1/fake/vcluster.go new file mode 100644 index 00000000000..8c5321f42b3 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1/fake/vcluster.go @@ -0,0 +1,202 @@ +//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 fake + +import ( + "context" + "encoding/json" + "fmt" + + "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" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + applyconfigurationsmountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1" + mountsv1alpha1client "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1" +) + +var vClustersResource = schema.GroupVersionResource{Group: "mounts.contrib.kcp.io", Version: "v1alpha1", Resource: "vclusters"} +var vClustersKind = schema.GroupVersionKind{Group: "mounts.contrib.kcp.io", Version: "v1alpha1", Kind: "VCluster"} + +type vClustersClusterClient struct { + *kcptesting.Fake +} + +// Cluster scopes the client down to a particular cluster. +func (c *vClustersClusterClient) Cluster(clusterPath logicalcluster.Path) mountsv1alpha1client.VClusterInterface { + if clusterPath == logicalcluster.Wildcard { + panic("A specific cluster must be provided when scoping, not the wildcard.") + } + + return &vClustersClient{Fake: c.Fake, ClusterPath: clusterPath} +} + +// List takes label and field selectors, and returns the list of VClusters that match those selectors across all clusters. +func (c *vClustersClusterClient) List(ctx context.Context, opts metav1.ListOptions) (*mountsv1alpha1.VClusterList, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootListAction(vClustersResource, vClustersKind, logicalcluster.Wildcard, opts), &mountsv1alpha1.VClusterList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &mountsv1alpha1.VClusterList{ListMeta: obj.(*mountsv1alpha1.VClusterList).ListMeta} + for _, item := range obj.(*mountsv1alpha1.VClusterList).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 VClusters across all clusters. +func (c *vClustersClusterClient) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(kcptesting.NewRootWatchAction(vClustersResource, logicalcluster.Wildcard, opts)) +} + +type vClustersClient struct { + *kcptesting.Fake + ClusterPath logicalcluster.Path +} + +func (c *vClustersClient) Create(ctx context.Context, vCluster *mountsv1alpha1.VCluster, opts metav1.CreateOptions) (*mountsv1alpha1.VCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootCreateAction(vClustersResource, c.ClusterPath, vCluster), &mountsv1alpha1.VCluster{}) + if obj == nil { + return nil, err + } + return obj.(*mountsv1alpha1.VCluster), err +} + +func (c *vClustersClient) Update(ctx context.Context, vCluster *mountsv1alpha1.VCluster, opts metav1.UpdateOptions) (*mountsv1alpha1.VCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootUpdateAction(vClustersResource, c.ClusterPath, vCluster), &mountsv1alpha1.VCluster{}) + if obj == nil { + return nil, err + } + return obj.(*mountsv1alpha1.VCluster), err +} + +func (c *vClustersClient) UpdateStatus(ctx context.Context, vCluster *mountsv1alpha1.VCluster, opts metav1.UpdateOptions) (*mountsv1alpha1.VCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootUpdateSubresourceAction(vClustersResource, c.ClusterPath, "status", vCluster), &mountsv1alpha1.VCluster{}) + if obj == nil { + return nil, err + } + return obj.(*mountsv1alpha1.VCluster), err +} + +func (c *vClustersClient) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + _, err := c.Fake.Invokes(kcptesting.NewRootDeleteActionWithOptions(vClustersResource, c.ClusterPath, name, opts), &mountsv1alpha1.VCluster{}) + return err +} + +func (c *vClustersClient) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + action := kcptesting.NewRootDeleteCollectionAction(vClustersResource, c.ClusterPath, listOpts) + + _, err := c.Fake.Invokes(action, &mountsv1alpha1.VClusterList{}) + return err +} + +func (c *vClustersClient) Get(ctx context.Context, name string, options metav1.GetOptions) (*mountsv1alpha1.VCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootGetAction(vClustersResource, c.ClusterPath, name), &mountsv1alpha1.VCluster{}) + if obj == nil { + return nil, err + } + return obj.(*mountsv1alpha1.VCluster), err +} + +// List takes label and field selectors, and returns the list of VClusters that match those selectors. +func (c *vClustersClient) List(ctx context.Context, opts metav1.ListOptions) (*mountsv1alpha1.VClusterList, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootListAction(vClustersResource, vClustersKind, c.ClusterPath, opts), &mountsv1alpha1.VClusterList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &mountsv1alpha1.VClusterList{ListMeta: obj.(*mountsv1alpha1.VClusterList).ListMeta} + for _, item := range obj.(*mountsv1alpha1.VClusterList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +func (c *vClustersClient) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(kcptesting.NewRootWatchAction(vClustersResource, c.ClusterPath, opts)) +} + +func (c *vClustersClient) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (*mountsv1alpha1.VCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootPatchSubresourceAction(vClustersResource, c.ClusterPath, name, pt, data, subresources...), &mountsv1alpha1.VCluster{}) + if obj == nil { + return nil, err + } + return obj.(*mountsv1alpha1.VCluster), err +} + +func (c *vClustersClient) Apply(ctx context.Context, applyConfiguration *applyconfigurationsmountsv1alpha1.VClusterApplyConfiguration, opts metav1.ApplyOptions) (*mountsv1alpha1.VCluster, error) { + if applyConfiguration == nil { + return nil, fmt.Errorf("applyConfiguration provided to Apply must not be nil") + } + data, err := json.Marshal(applyConfiguration) + if err != nil { + return nil, err + } + name := applyConfiguration.Name + if name == nil { + return nil, fmt.Errorf("applyConfiguration.Name must be provided to Apply") + } + obj, err := c.Fake.Invokes(kcptesting.NewRootPatchSubresourceAction(vClustersResource, c.ClusterPath, *name, types.ApplyPatchType, data), &mountsv1alpha1.VCluster{}) + if obj == nil { + return nil, err + } + return obj.(*mountsv1alpha1.VCluster), err +} + +func (c *vClustersClient) ApplyStatus(ctx context.Context, applyConfiguration *applyconfigurationsmountsv1alpha1.VClusterApplyConfiguration, opts metav1.ApplyOptions) (*mountsv1alpha1.VCluster, error) { + if applyConfiguration == nil { + return nil, fmt.Errorf("applyConfiguration provided to Apply must not be nil") + } + data, err := json.Marshal(applyConfiguration) + if err != nil { + return nil, err + } + name := applyConfiguration.Name + if name == nil { + return nil, fmt.Errorf("applyConfiguration.Name must be provided to Apply") + } + obj, err := c.Fake.Invokes(kcptesting.NewRootPatchSubresourceAction(vClustersResource, c.ClusterPath, *name, types.ApplyPatchType, data, "status"), &mountsv1alpha1.VCluster{}) + if obj == nil { + return nil, err + } + return obj.(*mountsv1alpha1.VCluster), err +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1/kubecluster.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1/kubecluster.go new file mode 100644 index 00000000000..72c69ef7965 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1/kubecluster.go @@ -0,0 +1,72 @@ +//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" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + mountsv1alpha1client "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1" +) + +// KubeClustersClusterGetter has a method to return a KubeClusterClusterInterface. +// A group's cluster client should implement this interface. +type KubeClustersClusterGetter interface { + KubeClusters() KubeClusterClusterInterface +} + +// KubeClusterClusterInterface can operate on KubeClusters across all clusters, +// or scope down to one cluster and return a mountsv1alpha1client.KubeClusterInterface. +type KubeClusterClusterInterface interface { + Cluster(logicalcluster.Path) mountsv1alpha1client.KubeClusterInterface + List(ctx context.Context, opts metav1.ListOptions) (*mountsv1alpha1.KubeClusterList, error) + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) +} + +type kubeClustersClusterInterface struct { + clientCache kcpclient.Cache[*mountsv1alpha1client.MountsV1alpha1Client] +} + +// Cluster scopes the client down to a particular cluster. +func (c *kubeClustersClusterInterface) Cluster(clusterPath logicalcluster.Path) mountsv1alpha1client.KubeClusterInterface { + if clusterPath == logicalcluster.Wildcard { + panic("A specific cluster must be provided when scoping, not the wildcard.") + } + + return c.clientCache.ClusterOrDie(clusterPath).KubeClusters() +} + +// List returns the entire collection of all KubeClusters across all clusters. +func (c *kubeClustersClusterInterface) List(ctx context.Context, opts metav1.ListOptions) (*mountsv1alpha1.KubeClusterList, error) { + return c.clientCache.ClusterOrDie(logicalcluster.Wildcard).KubeClusters().List(ctx, opts) +} + +// Watch begins to watch all KubeClusters across all clusters. +func (c *kubeClustersClusterInterface) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + return c.clientCache.ClusterOrDie(logicalcluster.Wildcard).KubeClusters().Watch(ctx, opts) +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1/mounts_client.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1/mounts_client.go new file mode 100644 index 00000000000..7d612cbbce2 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1/mounts_client.go @@ -0,0 +1,95 @@ +//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 ( + "net/http" + + kcpclient "github.com/kcp-dev/apimachinery/v2/pkg/client" + "github.com/kcp-dev/logicalcluster/v3" + + "k8s.io/client-go/rest" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1" +) + +type MountsV1alpha1ClusterInterface interface { + MountsV1alpha1ClusterScoper + KubeClustersClusterGetter + VClustersClusterGetter +} + +type MountsV1alpha1ClusterScoper interface { + Cluster(logicalcluster.Path) mountsv1alpha1.MountsV1alpha1Interface +} + +type MountsV1alpha1ClusterClient struct { + clientCache kcpclient.Cache[*mountsv1alpha1.MountsV1alpha1Client] +} + +func (c *MountsV1alpha1ClusterClient) Cluster(clusterPath logicalcluster.Path) mountsv1alpha1.MountsV1alpha1Interface { + if clusterPath == logicalcluster.Wildcard { + panic("A specific cluster must be provided when scoping, not the wildcard.") + } + return c.clientCache.ClusterOrDie(clusterPath) +} + +func (c *MountsV1alpha1ClusterClient) KubeClusters() KubeClusterClusterInterface { + return &kubeClustersClusterInterface{clientCache: c.clientCache} +} + +func (c *MountsV1alpha1ClusterClient) VClusters() VClusterClusterInterface { + return &vClustersClusterInterface{clientCache: c.clientCache} +} + +// NewForConfig creates a new MountsV1alpha1ClusterClient for the given config. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*MountsV1alpha1ClusterClient, error) { + client, err := rest.HTTPClientFor(c) + if err != nil { + return nil, err + } + return NewForConfigAndClient(c, client) +} + +// NewForConfigAndClient creates a new MountsV1alpha1ClusterClient for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +func NewForConfigAndClient(c *rest.Config, h *http.Client) (*MountsV1alpha1ClusterClient, error) { + cache := kcpclient.NewCache(c, h, &kcpclient.Constructor[*mountsv1alpha1.MountsV1alpha1Client]{ + NewForConfigAndClient: mountsv1alpha1.NewForConfigAndClient, + }) + if _, err := cache.Cluster(logicalcluster.Name("root").Path()); err != nil { + return nil, err + } + return &MountsV1alpha1ClusterClient{clientCache: cache}, nil +} + +// NewForConfigOrDie creates a new MountsV1alpha1ClusterClient for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *MountsV1alpha1ClusterClient { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1/vcluster.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1/vcluster.go new file mode 100644 index 00000000000..035a22273c2 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/mounts/v1alpha1/vcluster.go @@ -0,0 +1,72 @@ +//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" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + mountsv1alpha1client "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1" +) + +// VClustersClusterGetter has a method to return a VClusterClusterInterface. +// A group's cluster client should implement this interface. +type VClustersClusterGetter interface { + VClusters() VClusterClusterInterface +} + +// VClusterClusterInterface can operate on VClusters across all clusters, +// or scope down to one cluster and return a mountsv1alpha1client.VClusterInterface. +type VClusterClusterInterface interface { + Cluster(logicalcluster.Path) mountsv1alpha1client.VClusterInterface + List(ctx context.Context, opts metav1.ListOptions) (*mountsv1alpha1.VClusterList, error) + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) +} + +type vClustersClusterInterface struct { + clientCache kcpclient.Cache[*mountsv1alpha1client.MountsV1alpha1Client] +} + +// Cluster scopes the client down to a particular cluster. +func (c *vClustersClusterInterface) Cluster(clusterPath logicalcluster.Path) mountsv1alpha1client.VClusterInterface { + if clusterPath == logicalcluster.Wildcard { + panic("A specific cluster must be provided when scoping, not the wildcard.") + } + + return c.clientCache.ClusterOrDie(clusterPath).VClusters() +} + +// List returns the entire collection of all VClusters across all clusters. +func (c *vClustersClusterInterface) List(ctx context.Context, opts metav1.ListOptions) (*mountsv1alpha1.VClusterList, error) { + return c.clientCache.ClusterOrDie(logicalcluster.Wildcard).VClusters().List(ctx, opts) +} + +// Watch begins to watch all VClusters across all clusters. +func (c *vClustersClusterInterface) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + return c.clientCache.ClusterOrDie(logicalcluster.Wildcard).VClusters().Watch(ctx, opts) +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1/fake/targetkubecluster.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1/fake/targetkubecluster.go new file mode 100644 index 00000000000..3db53a5caa6 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1/fake/targetkubecluster.go @@ -0,0 +1,202 @@ +//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 fake + +import ( + "context" + "encoding/json" + "fmt" + + "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" + + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" + applyconfigurationstargetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1" + targetsv1alpha1client "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1" +) + +var targetKubeClustersResource = schema.GroupVersionResource{Group: "targets.contrib.kcp.io", Version: "v1alpha1", Resource: "targetkubeclusters"} +var targetKubeClustersKind = schema.GroupVersionKind{Group: "targets.contrib.kcp.io", Version: "v1alpha1", Kind: "TargetKubeCluster"} + +type targetKubeClustersClusterClient struct { + *kcptesting.Fake +} + +// Cluster scopes the client down to a particular cluster. +func (c *targetKubeClustersClusterClient) Cluster(clusterPath logicalcluster.Path) targetsv1alpha1client.TargetKubeClusterInterface { + if clusterPath == logicalcluster.Wildcard { + panic("A specific cluster must be provided when scoping, not the wildcard.") + } + + return &targetKubeClustersClient{Fake: c.Fake, ClusterPath: clusterPath} +} + +// List takes label and field selectors, and returns the list of TargetKubeClusters that match those selectors across all clusters. +func (c *targetKubeClustersClusterClient) List(ctx context.Context, opts metav1.ListOptions) (*targetsv1alpha1.TargetKubeClusterList, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootListAction(targetKubeClustersResource, targetKubeClustersKind, logicalcluster.Wildcard, opts), &targetsv1alpha1.TargetKubeClusterList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &targetsv1alpha1.TargetKubeClusterList{ListMeta: obj.(*targetsv1alpha1.TargetKubeClusterList).ListMeta} + for _, item := range obj.(*targetsv1alpha1.TargetKubeClusterList).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 TargetKubeClusters across all clusters. +func (c *targetKubeClustersClusterClient) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(kcptesting.NewRootWatchAction(targetKubeClustersResource, logicalcluster.Wildcard, opts)) +} + +type targetKubeClustersClient struct { + *kcptesting.Fake + ClusterPath logicalcluster.Path +} + +func (c *targetKubeClustersClient) Create(ctx context.Context, targetKubeCluster *targetsv1alpha1.TargetKubeCluster, opts metav1.CreateOptions) (*targetsv1alpha1.TargetKubeCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootCreateAction(targetKubeClustersResource, c.ClusterPath, targetKubeCluster), &targetsv1alpha1.TargetKubeCluster{}) + if obj == nil { + return nil, err + } + return obj.(*targetsv1alpha1.TargetKubeCluster), err +} + +func (c *targetKubeClustersClient) Update(ctx context.Context, targetKubeCluster *targetsv1alpha1.TargetKubeCluster, opts metav1.UpdateOptions) (*targetsv1alpha1.TargetKubeCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootUpdateAction(targetKubeClustersResource, c.ClusterPath, targetKubeCluster), &targetsv1alpha1.TargetKubeCluster{}) + if obj == nil { + return nil, err + } + return obj.(*targetsv1alpha1.TargetKubeCluster), err +} + +func (c *targetKubeClustersClient) UpdateStatus(ctx context.Context, targetKubeCluster *targetsv1alpha1.TargetKubeCluster, opts metav1.UpdateOptions) (*targetsv1alpha1.TargetKubeCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootUpdateSubresourceAction(targetKubeClustersResource, c.ClusterPath, "status", targetKubeCluster), &targetsv1alpha1.TargetKubeCluster{}) + if obj == nil { + return nil, err + } + return obj.(*targetsv1alpha1.TargetKubeCluster), err +} + +func (c *targetKubeClustersClient) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + _, err := c.Fake.Invokes(kcptesting.NewRootDeleteActionWithOptions(targetKubeClustersResource, c.ClusterPath, name, opts), &targetsv1alpha1.TargetKubeCluster{}) + return err +} + +func (c *targetKubeClustersClient) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + action := kcptesting.NewRootDeleteCollectionAction(targetKubeClustersResource, c.ClusterPath, listOpts) + + _, err := c.Fake.Invokes(action, &targetsv1alpha1.TargetKubeClusterList{}) + return err +} + +func (c *targetKubeClustersClient) Get(ctx context.Context, name string, options metav1.GetOptions) (*targetsv1alpha1.TargetKubeCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootGetAction(targetKubeClustersResource, c.ClusterPath, name), &targetsv1alpha1.TargetKubeCluster{}) + if obj == nil { + return nil, err + } + return obj.(*targetsv1alpha1.TargetKubeCluster), err +} + +// List takes label and field selectors, and returns the list of TargetKubeClusters that match those selectors. +func (c *targetKubeClustersClient) List(ctx context.Context, opts metav1.ListOptions) (*targetsv1alpha1.TargetKubeClusterList, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootListAction(targetKubeClustersResource, targetKubeClustersKind, c.ClusterPath, opts), &targetsv1alpha1.TargetKubeClusterList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &targetsv1alpha1.TargetKubeClusterList{ListMeta: obj.(*targetsv1alpha1.TargetKubeClusterList).ListMeta} + for _, item := range obj.(*targetsv1alpha1.TargetKubeClusterList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +func (c *targetKubeClustersClient) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(kcptesting.NewRootWatchAction(targetKubeClustersResource, c.ClusterPath, opts)) +} + +func (c *targetKubeClustersClient) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (*targetsv1alpha1.TargetKubeCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootPatchSubresourceAction(targetKubeClustersResource, c.ClusterPath, name, pt, data, subresources...), &targetsv1alpha1.TargetKubeCluster{}) + if obj == nil { + return nil, err + } + return obj.(*targetsv1alpha1.TargetKubeCluster), err +} + +func (c *targetKubeClustersClient) Apply(ctx context.Context, applyConfiguration *applyconfigurationstargetsv1alpha1.TargetKubeClusterApplyConfiguration, opts metav1.ApplyOptions) (*targetsv1alpha1.TargetKubeCluster, error) { + if applyConfiguration == nil { + return nil, fmt.Errorf("applyConfiguration provided to Apply must not be nil") + } + data, err := json.Marshal(applyConfiguration) + if err != nil { + return nil, err + } + name := applyConfiguration.Name + if name == nil { + return nil, fmt.Errorf("applyConfiguration.Name must be provided to Apply") + } + obj, err := c.Fake.Invokes(kcptesting.NewRootPatchSubresourceAction(targetKubeClustersResource, c.ClusterPath, *name, types.ApplyPatchType, data), &targetsv1alpha1.TargetKubeCluster{}) + if obj == nil { + return nil, err + } + return obj.(*targetsv1alpha1.TargetKubeCluster), err +} + +func (c *targetKubeClustersClient) ApplyStatus(ctx context.Context, applyConfiguration *applyconfigurationstargetsv1alpha1.TargetKubeClusterApplyConfiguration, opts metav1.ApplyOptions) (*targetsv1alpha1.TargetKubeCluster, error) { + if applyConfiguration == nil { + return nil, fmt.Errorf("applyConfiguration provided to Apply must not be nil") + } + data, err := json.Marshal(applyConfiguration) + if err != nil { + return nil, err + } + name := applyConfiguration.Name + if name == nil { + return nil, fmt.Errorf("applyConfiguration.Name must be provided to Apply") + } + obj, err := c.Fake.Invokes(kcptesting.NewRootPatchSubresourceAction(targetKubeClustersResource, c.ClusterPath, *name, types.ApplyPatchType, data, "status"), &targetsv1alpha1.TargetKubeCluster{}) + if obj == nil { + return nil, err + } + return obj.(*targetsv1alpha1.TargetKubeCluster), err +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1/fake/targets_client.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1/fake/targets_client.go new file mode 100644 index 00000000000..4c5bb9c079a --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1/fake/targets_client.go @@ -0,0 +1,73 @@ +//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 fake + +import ( + "github.com/kcp-dev/logicalcluster/v3" + + kcptesting "github.com/kcp-dev/client-go/third_party/k8s.io/client-go/testing" + "k8s.io/client-go/rest" + + kcptargetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1" + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1" +) + +var _ kcptargetsv1alpha1.TargetsV1alpha1ClusterInterface = (*TargetsV1alpha1ClusterClient)(nil) + +type TargetsV1alpha1ClusterClient struct { + *kcptesting.Fake +} + +func (c *TargetsV1alpha1ClusterClient) Cluster(clusterPath logicalcluster.Path) targetsv1alpha1.TargetsV1alpha1Interface { + if clusterPath == logicalcluster.Wildcard { + panic("A specific cluster must be provided when scoping, not the wildcard.") + } + return &TargetsV1alpha1Client{Fake: c.Fake, ClusterPath: clusterPath} +} + +func (c *TargetsV1alpha1ClusterClient) TargetKubeClusters() kcptargetsv1alpha1.TargetKubeClusterClusterInterface { + return &targetKubeClustersClusterClient{Fake: c.Fake} +} + +func (c *TargetsV1alpha1ClusterClient) TargetVClusters() kcptargetsv1alpha1.TargetVClusterClusterInterface { + return &targetVClustersClusterClient{Fake: c.Fake} +} + +var _ targetsv1alpha1.TargetsV1alpha1Interface = (*TargetsV1alpha1Client)(nil) + +type TargetsV1alpha1Client struct { + *kcptesting.Fake + ClusterPath logicalcluster.Path +} + +func (c *TargetsV1alpha1Client) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} + +func (c *TargetsV1alpha1Client) TargetKubeClusters() targetsv1alpha1.TargetKubeClusterInterface { + return &targetKubeClustersClient{Fake: c.Fake, ClusterPath: c.ClusterPath} +} + +func (c *TargetsV1alpha1Client) TargetVClusters() targetsv1alpha1.TargetVClusterInterface { + return &targetVClustersClient{Fake: c.Fake, ClusterPath: c.ClusterPath} +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1/fake/targetvcluster.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1/fake/targetvcluster.go new file mode 100644 index 00000000000..b5edc050edd --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1/fake/targetvcluster.go @@ -0,0 +1,202 @@ +//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 fake + +import ( + "context" + "encoding/json" + "fmt" + + "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" + + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" + applyconfigurationstargetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1" + targetsv1alpha1client "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1" +) + +var targetVClustersResource = schema.GroupVersionResource{Group: "targets.contrib.kcp.io", Version: "v1alpha1", Resource: "targetvclusters"} +var targetVClustersKind = schema.GroupVersionKind{Group: "targets.contrib.kcp.io", Version: "v1alpha1", Kind: "TargetVCluster"} + +type targetVClustersClusterClient struct { + *kcptesting.Fake +} + +// Cluster scopes the client down to a particular cluster. +func (c *targetVClustersClusterClient) Cluster(clusterPath logicalcluster.Path) targetsv1alpha1client.TargetVClusterInterface { + if clusterPath == logicalcluster.Wildcard { + panic("A specific cluster must be provided when scoping, not the wildcard.") + } + + return &targetVClustersClient{Fake: c.Fake, ClusterPath: clusterPath} +} + +// List takes label and field selectors, and returns the list of TargetVClusters that match those selectors across all clusters. +func (c *targetVClustersClusterClient) List(ctx context.Context, opts metav1.ListOptions) (*targetsv1alpha1.TargetVClusterList, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootListAction(targetVClustersResource, targetVClustersKind, logicalcluster.Wildcard, opts), &targetsv1alpha1.TargetVClusterList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &targetsv1alpha1.TargetVClusterList{ListMeta: obj.(*targetsv1alpha1.TargetVClusterList).ListMeta} + for _, item := range obj.(*targetsv1alpha1.TargetVClusterList).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 TargetVClusters across all clusters. +func (c *targetVClustersClusterClient) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(kcptesting.NewRootWatchAction(targetVClustersResource, logicalcluster.Wildcard, opts)) +} + +type targetVClustersClient struct { + *kcptesting.Fake + ClusterPath logicalcluster.Path +} + +func (c *targetVClustersClient) Create(ctx context.Context, targetVCluster *targetsv1alpha1.TargetVCluster, opts metav1.CreateOptions) (*targetsv1alpha1.TargetVCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootCreateAction(targetVClustersResource, c.ClusterPath, targetVCluster), &targetsv1alpha1.TargetVCluster{}) + if obj == nil { + return nil, err + } + return obj.(*targetsv1alpha1.TargetVCluster), err +} + +func (c *targetVClustersClient) Update(ctx context.Context, targetVCluster *targetsv1alpha1.TargetVCluster, opts metav1.UpdateOptions) (*targetsv1alpha1.TargetVCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootUpdateAction(targetVClustersResource, c.ClusterPath, targetVCluster), &targetsv1alpha1.TargetVCluster{}) + if obj == nil { + return nil, err + } + return obj.(*targetsv1alpha1.TargetVCluster), err +} + +func (c *targetVClustersClient) UpdateStatus(ctx context.Context, targetVCluster *targetsv1alpha1.TargetVCluster, opts metav1.UpdateOptions) (*targetsv1alpha1.TargetVCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootUpdateSubresourceAction(targetVClustersResource, c.ClusterPath, "status", targetVCluster), &targetsv1alpha1.TargetVCluster{}) + if obj == nil { + return nil, err + } + return obj.(*targetsv1alpha1.TargetVCluster), err +} + +func (c *targetVClustersClient) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + _, err := c.Fake.Invokes(kcptesting.NewRootDeleteActionWithOptions(targetVClustersResource, c.ClusterPath, name, opts), &targetsv1alpha1.TargetVCluster{}) + return err +} + +func (c *targetVClustersClient) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + action := kcptesting.NewRootDeleteCollectionAction(targetVClustersResource, c.ClusterPath, listOpts) + + _, err := c.Fake.Invokes(action, &targetsv1alpha1.TargetVClusterList{}) + return err +} + +func (c *targetVClustersClient) Get(ctx context.Context, name string, options metav1.GetOptions) (*targetsv1alpha1.TargetVCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootGetAction(targetVClustersResource, c.ClusterPath, name), &targetsv1alpha1.TargetVCluster{}) + if obj == nil { + return nil, err + } + return obj.(*targetsv1alpha1.TargetVCluster), err +} + +// List takes label and field selectors, and returns the list of TargetVClusters that match those selectors. +func (c *targetVClustersClient) List(ctx context.Context, opts metav1.ListOptions) (*targetsv1alpha1.TargetVClusterList, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootListAction(targetVClustersResource, targetVClustersKind, c.ClusterPath, opts), &targetsv1alpha1.TargetVClusterList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &targetsv1alpha1.TargetVClusterList{ListMeta: obj.(*targetsv1alpha1.TargetVClusterList).ListMeta} + for _, item := range obj.(*targetsv1alpha1.TargetVClusterList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +func (c *targetVClustersClient) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(kcptesting.NewRootWatchAction(targetVClustersResource, c.ClusterPath, opts)) +} + +func (c *targetVClustersClient) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (*targetsv1alpha1.TargetVCluster, error) { + obj, err := c.Fake.Invokes(kcptesting.NewRootPatchSubresourceAction(targetVClustersResource, c.ClusterPath, name, pt, data, subresources...), &targetsv1alpha1.TargetVCluster{}) + if obj == nil { + return nil, err + } + return obj.(*targetsv1alpha1.TargetVCluster), err +} + +func (c *targetVClustersClient) Apply(ctx context.Context, applyConfiguration *applyconfigurationstargetsv1alpha1.TargetVClusterApplyConfiguration, opts metav1.ApplyOptions) (*targetsv1alpha1.TargetVCluster, error) { + if applyConfiguration == nil { + return nil, fmt.Errorf("applyConfiguration provided to Apply must not be nil") + } + data, err := json.Marshal(applyConfiguration) + if err != nil { + return nil, err + } + name := applyConfiguration.Name + if name == nil { + return nil, fmt.Errorf("applyConfiguration.Name must be provided to Apply") + } + obj, err := c.Fake.Invokes(kcptesting.NewRootPatchSubresourceAction(targetVClustersResource, c.ClusterPath, *name, types.ApplyPatchType, data), &targetsv1alpha1.TargetVCluster{}) + if obj == nil { + return nil, err + } + return obj.(*targetsv1alpha1.TargetVCluster), err +} + +func (c *targetVClustersClient) ApplyStatus(ctx context.Context, applyConfiguration *applyconfigurationstargetsv1alpha1.TargetVClusterApplyConfiguration, opts metav1.ApplyOptions) (*targetsv1alpha1.TargetVCluster, error) { + if applyConfiguration == nil { + return nil, fmt.Errorf("applyConfiguration provided to Apply must not be nil") + } + data, err := json.Marshal(applyConfiguration) + if err != nil { + return nil, err + } + name := applyConfiguration.Name + if name == nil { + return nil, fmt.Errorf("applyConfiguration.Name must be provided to Apply") + } + obj, err := c.Fake.Invokes(kcptesting.NewRootPatchSubresourceAction(targetVClustersResource, c.ClusterPath, *name, types.ApplyPatchType, data, "status"), &targetsv1alpha1.TargetVCluster{}) + if obj == nil { + return nil, err + } + return obj.(*targetsv1alpha1.TargetVCluster), err +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1/targetkubecluster.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1/targetkubecluster.go new file mode 100644 index 00000000000..7e6e66ffd79 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1/targetkubecluster.go @@ -0,0 +1,72 @@ +//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" + + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" + targetsv1alpha1client "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1" +) + +// TargetKubeClustersClusterGetter has a method to return a TargetKubeClusterClusterInterface. +// A group's cluster client should implement this interface. +type TargetKubeClustersClusterGetter interface { + TargetKubeClusters() TargetKubeClusterClusterInterface +} + +// TargetKubeClusterClusterInterface can operate on TargetKubeClusters across all clusters, +// or scope down to one cluster and return a targetsv1alpha1client.TargetKubeClusterInterface. +type TargetKubeClusterClusterInterface interface { + Cluster(logicalcluster.Path) targetsv1alpha1client.TargetKubeClusterInterface + List(ctx context.Context, opts metav1.ListOptions) (*targetsv1alpha1.TargetKubeClusterList, error) + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) +} + +type targetKubeClustersClusterInterface struct { + clientCache kcpclient.Cache[*targetsv1alpha1client.TargetsV1alpha1Client] +} + +// Cluster scopes the client down to a particular cluster. +func (c *targetKubeClustersClusterInterface) Cluster(clusterPath logicalcluster.Path) targetsv1alpha1client.TargetKubeClusterInterface { + if clusterPath == logicalcluster.Wildcard { + panic("A specific cluster must be provided when scoping, not the wildcard.") + } + + return c.clientCache.ClusterOrDie(clusterPath).TargetKubeClusters() +} + +// List returns the entire collection of all TargetKubeClusters across all clusters. +func (c *targetKubeClustersClusterInterface) List(ctx context.Context, opts metav1.ListOptions) (*targetsv1alpha1.TargetKubeClusterList, error) { + return c.clientCache.ClusterOrDie(logicalcluster.Wildcard).TargetKubeClusters().List(ctx, opts) +} + +// Watch begins to watch all TargetKubeClusters across all clusters. +func (c *targetKubeClustersClusterInterface) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + return c.clientCache.ClusterOrDie(logicalcluster.Wildcard).TargetKubeClusters().Watch(ctx, opts) +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1/targets_client.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1/targets_client.go new file mode 100644 index 00000000000..58f53091e23 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1/targets_client.go @@ -0,0 +1,95 @@ +//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 ( + "net/http" + + kcpclient "github.com/kcp-dev/apimachinery/v2/pkg/client" + "github.com/kcp-dev/logicalcluster/v3" + + "k8s.io/client-go/rest" + + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1" +) + +type TargetsV1alpha1ClusterInterface interface { + TargetsV1alpha1ClusterScoper + TargetKubeClustersClusterGetter + TargetVClustersClusterGetter +} + +type TargetsV1alpha1ClusterScoper interface { + Cluster(logicalcluster.Path) targetsv1alpha1.TargetsV1alpha1Interface +} + +type TargetsV1alpha1ClusterClient struct { + clientCache kcpclient.Cache[*targetsv1alpha1.TargetsV1alpha1Client] +} + +func (c *TargetsV1alpha1ClusterClient) Cluster(clusterPath logicalcluster.Path) targetsv1alpha1.TargetsV1alpha1Interface { + if clusterPath == logicalcluster.Wildcard { + panic("A specific cluster must be provided when scoping, not the wildcard.") + } + return c.clientCache.ClusterOrDie(clusterPath) +} + +func (c *TargetsV1alpha1ClusterClient) TargetKubeClusters() TargetKubeClusterClusterInterface { + return &targetKubeClustersClusterInterface{clientCache: c.clientCache} +} + +func (c *TargetsV1alpha1ClusterClient) TargetVClusters() TargetVClusterClusterInterface { + return &targetVClustersClusterInterface{clientCache: c.clientCache} +} + +// NewForConfig creates a new TargetsV1alpha1ClusterClient for the given config. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*TargetsV1alpha1ClusterClient, error) { + client, err := rest.HTTPClientFor(c) + if err != nil { + return nil, err + } + return NewForConfigAndClient(c, client) +} + +// NewForConfigAndClient creates a new TargetsV1alpha1ClusterClient for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +func NewForConfigAndClient(c *rest.Config, h *http.Client) (*TargetsV1alpha1ClusterClient, error) { + cache := kcpclient.NewCache(c, h, &kcpclient.Constructor[*targetsv1alpha1.TargetsV1alpha1Client]{ + NewForConfigAndClient: targetsv1alpha1.NewForConfigAndClient, + }) + if _, err := cache.Cluster(logicalcluster.Name("root").Path()); err != nil { + return nil, err + } + return &TargetsV1alpha1ClusterClient{clientCache: cache}, nil +} + +// NewForConfigOrDie creates a new TargetsV1alpha1ClusterClient for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *TargetsV1alpha1ClusterClient { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1/targetvcluster.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1/targetvcluster.go new file mode 100644 index 00000000000..7a418b9c77c --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster/typed/targets/v1alpha1/targetvcluster.go @@ -0,0 +1,72 @@ +//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" + + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" + targetsv1alpha1client "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1" +) + +// TargetVClustersClusterGetter has a method to return a TargetVClusterClusterInterface. +// A group's cluster client should implement this interface. +type TargetVClustersClusterGetter interface { + TargetVClusters() TargetVClusterClusterInterface +} + +// TargetVClusterClusterInterface can operate on TargetVClusters across all clusters, +// or scope down to one cluster and return a targetsv1alpha1client.TargetVClusterInterface. +type TargetVClusterClusterInterface interface { + Cluster(logicalcluster.Path) targetsv1alpha1client.TargetVClusterInterface + List(ctx context.Context, opts metav1.ListOptions) (*targetsv1alpha1.TargetVClusterList, error) + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) +} + +type targetVClustersClusterInterface struct { + clientCache kcpclient.Cache[*targetsv1alpha1client.TargetsV1alpha1Client] +} + +// Cluster scopes the client down to a particular cluster. +func (c *targetVClustersClusterInterface) Cluster(clusterPath logicalcluster.Path) targetsv1alpha1client.TargetVClusterInterface { + if clusterPath == logicalcluster.Wildcard { + panic("A specific cluster must be provided when scoping, not the wildcard.") + } + + return c.clientCache.ClusterOrDie(clusterPath).TargetVClusters() +} + +// List returns the entire collection of all TargetVClusters across all clusters. +func (c *targetVClustersClusterInterface) List(ctx context.Context, opts metav1.ListOptions) (*targetsv1alpha1.TargetVClusterList, error) { + return c.clientCache.ClusterOrDie(logicalcluster.Wildcard).TargetVClusters().List(ctx, opts) +} + +// Watch begins to watch all TargetVClusters across all clusters. +func (c *targetVClustersClusterInterface) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + return c.clientCache.ClusterOrDie(logicalcluster.Wildcard).TargetVClusters().Watch(ctx, opts) +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/fake/clientset_generated.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/fake/clientset_generated.go new file mode 100644 index 00000000000..62e4dcfbdcf --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/fake/clientset_generated.go @@ -0,0 +1,130 @@ +/* +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 ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/discovery" + fakediscovery "k8s.io/client-go/discovery/fake" + "k8s.io/client-go/testing" + + applyconfiguration "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration" + clientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned" + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1" + fakemountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/fake" + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1" + faketargetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/fake" +) + +// NewSimpleClientset returns a clientset that will respond with the provided objects. +// It's backed by a very simple object tracker that processes creates, updates and deletions as-is, +// without applying any field management, validations and/or defaults. It shouldn't be considered a replacement +// for a real clientset and is mostly useful in simple unit tests. +// +// DEPRECATED: NewClientset replaces this with support for field management, which significantly improves +// server side apply testing. NewClientset is only available when apply configurations are generated (e.g. +// via --with-applyconfig). +func NewSimpleClientset(objects ...runtime.Object) *Clientset { + o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) + for _, obj := range objects { + if err := o.Add(obj); err != nil { + panic(err) + } + } + + cs := &Clientset{tracker: o} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + gvr := action.GetResource() + ns := action.GetNamespace() + watch, err := o.Watch(gvr, ns) + if err != nil { + return false, nil, err + } + return true, watch, nil + }) + + return cs +} + +// Clientset implements clientset.Interface. Meant to be embedded into a +// struct to get a default implementation. This makes faking out just the method +// you want to test easier. +type Clientset struct { + testing.Fake + discovery *fakediscovery.FakeDiscovery + tracker testing.ObjectTracker +} + +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + return c.discovery +} + +func (c *Clientset) Tracker() testing.ObjectTracker { + return c.tracker +} + +// NewClientset returns a clientset that will respond with the provided objects. +// It's backed by a very simple object tracker that processes creates, updates and deletions as-is, +// without applying any validations and/or defaults. It shouldn't be considered a replacement +// for a real clientset and is mostly useful in simple unit tests. +func NewClientset(objects ...runtime.Object) *Clientset { + o := testing.NewFieldManagedObjectTracker( + scheme, + codecs.UniversalDecoder(), + applyconfiguration.NewTypeConverter(scheme), + ) + for _, obj := range objects { + if err := o.Add(obj); err != nil { + panic(err) + } + } + + cs := &Clientset{tracker: o} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + gvr := action.GetResource() + ns := action.GetNamespace() + watch, err := o.Watch(gvr, ns) + if err != nil { + return false, nil, err + } + return true, watch, nil + }) + + return cs +} + +var ( + _ clientset.Interface = &Clientset{} + _ testing.FakeClient = &Clientset{} +) + +// MountsV1alpha1 retrieves the MountsV1alpha1Client +func (c *Clientset) MountsV1alpha1() mountsv1alpha1.MountsV1alpha1Interface { + return &fakemountsv1alpha1.FakeMountsV1alpha1{Fake: &c.Fake} +} + +// TargetsV1alpha1 retrieves the TargetsV1alpha1Client +func (c *Clientset) TargetsV1alpha1() targetsv1alpha1.TargetsV1alpha1Interface { + return &faketargetsv1alpha1.FakeTargetsV1alpha1{Fake: &c.Fake} +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/fake/doc.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/fake/doc.go new file mode 100644 index 00000000000..d134e6f3374 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/fake/doc.go @@ -0,0 +1,20 @@ +/* +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. + +// This package has the automatically generated fake clientset. +package fake diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/fake/register.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/fake/register.go new file mode 100644 index 00000000000..63f6cc2dc20 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/fake/register.go @@ -0,0 +1,59 @@ +/* +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 ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" +) + +var scheme = runtime.NewScheme() +var codecs = serializer.NewCodecFactory(scheme) + +var localSchemeBuilder = runtime.SchemeBuilder{ + mountsv1alpha1.AddToScheme, + targetsv1alpha1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(scheme)) +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/scheme/doc.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/scheme/doc.go new file mode 100644 index 00000000000..0a0dd78eab2 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/scheme/doc.go @@ -0,0 +1,20 @@ +/* +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. + +// This package contains the scheme of the automatically generated clientset. +package scheme diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/scheme/register.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/scheme/register.go new file mode 100644 index 00000000000..00f13e858bd --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/scheme/register.go @@ -0,0 +1,59 @@ +/* +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 scheme + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" +) + +var Scheme = runtime.NewScheme() +var Codecs = serializer.NewCodecFactory(Scheme) +var ParameterCodec = runtime.NewParameterCodec(Scheme) +var localSchemeBuilder = runtime.SchemeBuilder{ + mountsv1alpha1.AddToScheme, + targetsv1alpha1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(Scheme)) +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/doc.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/doc.go new file mode 100644 index 00000000000..364b93c7cfd --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/doc.go @@ -0,0 +1,20 @@ +/* +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. + +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/fake/doc.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/fake/doc.go new file mode 100644 index 00000000000..e388f29189e --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/fake/doc.go @@ -0,0 +1,20 @@ +/* +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 has the automatically generated clients. +package fake diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/fake/fake_kubecluster.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/fake/fake_kubecluster.go new file mode 100644 index 00000000000..83c048f4e83 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/fake/fake_kubecluster.go @@ -0,0 +1,187 @@ +/* +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" + json "encoding/json" + "fmt" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + + v1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1" +) + +// FakeKubeClusters implements KubeClusterInterface +type FakeKubeClusters struct { + Fake *FakeMountsV1alpha1 +} + +var kubeclustersResource = v1alpha1.SchemeGroupVersion.WithResource("kubeclusters") + +var kubeclustersKind = v1alpha1.SchemeGroupVersion.WithKind("KubeCluster") + +// Get takes name of the kubeCluster, and returns the corresponding kubeCluster object, and an error if there is any. +func (c *FakeKubeClusters) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.KubeCluster, err error) { + emptyResult := &v1alpha1.KubeCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootGetActionWithOptions(kubeclustersResource, name, options), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.KubeCluster), err +} + +// List takes label and field selectors, and returns the list of KubeClusters that match those selectors. +func (c *FakeKubeClusters) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.KubeClusterList, err error) { + emptyResult := &v1alpha1.KubeClusterList{} + obj, err := c.Fake. + Invokes(testing.NewRootListActionWithOptions(kubeclustersResource, kubeclustersKind, opts), emptyResult) + if obj == nil { + return emptyResult, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.KubeClusterList{ListMeta: obj.(*v1alpha1.KubeClusterList).ListMeta} + for _, item := range obj.(*v1alpha1.KubeClusterList).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 kubeClusters. +func (c *FakeKubeClusters) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchActionWithOptions(kubeclustersResource, opts)) +} + +// Create takes the representation of a kubeCluster and creates it. Returns the server's representation of the kubeCluster, and an error, if there is any. +func (c *FakeKubeClusters) Create(ctx context.Context, kubeCluster *v1alpha1.KubeCluster, opts v1.CreateOptions) (result *v1alpha1.KubeCluster, err error) { + emptyResult := &v1alpha1.KubeCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootCreateActionWithOptions(kubeclustersResource, kubeCluster, opts), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.KubeCluster), err +} + +// Update takes the representation of a kubeCluster and updates it. Returns the server's representation of the kubeCluster, and an error, if there is any. +func (c *FakeKubeClusters) Update(ctx context.Context, kubeCluster *v1alpha1.KubeCluster, opts v1.UpdateOptions) (result *v1alpha1.KubeCluster, err error) { + emptyResult := &v1alpha1.KubeCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootUpdateActionWithOptions(kubeclustersResource, kubeCluster, opts), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.KubeCluster), 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 *FakeKubeClusters) UpdateStatus(ctx context.Context, kubeCluster *v1alpha1.KubeCluster, opts v1.UpdateOptions) (result *v1alpha1.KubeCluster, err error) { + emptyResult := &v1alpha1.KubeCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceActionWithOptions(kubeclustersResource, "status", kubeCluster, opts), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.KubeCluster), err +} + +// Delete takes name of the kubeCluster and deletes it. Returns an error if one occurs. +func (c *FakeKubeClusters) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteActionWithOptions(kubeclustersResource, name, opts), &v1alpha1.KubeCluster{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeKubeClusters) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewRootDeleteCollectionActionWithOptions(kubeclustersResource, opts, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.KubeClusterList{}) + return err +} + +// Patch applies the patch and returns the patched kubeCluster. +func (c *FakeKubeClusters) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.KubeCluster, err error) { + emptyResult := &v1alpha1.KubeCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceActionWithOptions(kubeclustersResource, name, pt, data, opts, subresources...), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.KubeCluster), err +} + +// Apply takes the given apply declarative configuration, applies it and returns the applied kubeCluster. +func (c *FakeKubeClusters) Apply(ctx context.Context, kubeCluster *mountsv1alpha1.KubeClusterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.KubeCluster, err error) { + if kubeCluster == nil { + return nil, fmt.Errorf("kubeCluster provided to Apply must not be nil") + } + data, err := json.Marshal(kubeCluster) + if err != nil { + return nil, err + } + name := kubeCluster.Name + if name == nil { + return nil, fmt.Errorf("kubeCluster.Name must be provided to Apply") + } + emptyResult := &v1alpha1.KubeCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceActionWithOptions(kubeclustersResource, *name, types.ApplyPatchType, data, opts.ToPatchOptions()), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.KubeCluster), err +} + +// ApplyStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). +func (c *FakeKubeClusters) ApplyStatus(ctx context.Context, kubeCluster *mountsv1alpha1.KubeClusterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.KubeCluster, err error) { + if kubeCluster == nil { + return nil, fmt.Errorf("kubeCluster provided to Apply must not be nil") + } + data, err := json.Marshal(kubeCluster) + if err != nil { + return nil, err + } + name := kubeCluster.Name + if name == nil { + return nil, fmt.Errorf("kubeCluster.Name must be provided to Apply") + } + emptyResult := &v1alpha1.KubeCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceActionWithOptions(kubeclustersResource, *name, types.ApplyPatchType, data, opts.ToPatchOptions(), "status"), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.KubeCluster), err +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/fake/fake_mounts_client.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/fake/fake_mounts_client.go new file mode 100644 index 00000000000..a2c89593563 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/fake/fake_mounts_client.go @@ -0,0 +1,45 @@ +/* +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 ( + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" + + v1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1" +) + +type FakeMountsV1alpha1 struct { + *testing.Fake +} + +func (c *FakeMountsV1alpha1) KubeClusters() v1alpha1.KubeClusterInterface { + return &FakeKubeClusters{c} +} + +func (c *FakeMountsV1alpha1) VClusters() v1alpha1.VClusterInterface { + return &FakeVClusters{c} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeMountsV1alpha1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/fake/fake_vcluster.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/fake/fake_vcluster.go new file mode 100644 index 00000000000..d9cf907878d --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/fake/fake_vcluster.go @@ -0,0 +1,187 @@ +/* +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" + json "encoding/json" + "fmt" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + + v1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1" +) + +// FakeVClusters implements VClusterInterface +type FakeVClusters struct { + Fake *FakeMountsV1alpha1 +} + +var vclustersResource = v1alpha1.SchemeGroupVersion.WithResource("vclusters") + +var vclustersKind = v1alpha1.SchemeGroupVersion.WithKind("VCluster") + +// Get takes name of the vCluster, and returns the corresponding vCluster object, and an error if there is any. +func (c *FakeVClusters) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.VCluster, err error) { + emptyResult := &v1alpha1.VCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootGetActionWithOptions(vclustersResource, name, options), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.VCluster), err +} + +// List takes label and field selectors, and returns the list of VClusters that match those selectors. +func (c *FakeVClusters) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.VClusterList, err error) { + emptyResult := &v1alpha1.VClusterList{} + obj, err := c.Fake. + Invokes(testing.NewRootListActionWithOptions(vclustersResource, vclustersKind, opts), emptyResult) + if obj == nil { + return emptyResult, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.VClusterList{ListMeta: obj.(*v1alpha1.VClusterList).ListMeta} + for _, item := range obj.(*v1alpha1.VClusterList).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 vClusters. +func (c *FakeVClusters) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchActionWithOptions(vclustersResource, opts)) +} + +// Create takes the representation of a vCluster and creates it. Returns the server's representation of the vCluster, and an error, if there is any. +func (c *FakeVClusters) Create(ctx context.Context, vCluster *v1alpha1.VCluster, opts v1.CreateOptions) (result *v1alpha1.VCluster, err error) { + emptyResult := &v1alpha1.VCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootCreateActionWithOptions(vclustersResource, vCluster, opts), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.VCluster), err +} + +// Update takes the representation of a vCluster and updates it. Returns the server's representation of the vCluster, and an error, if there is any. +func (c *FakeVClusters) Update(ctx context.Context, vCluster *v1alpha1.VCluster, opts v1.UpdateOptions) (result *v1alpha1.VCluster, err error) { + emptyResult := &v1alpha1.VCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootUpdateActionWithOptions(vclustersResource, vCluster, opts), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.VCluster), 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 *FakeVClusters) UpdateStatus(ctx context.Context, vCluster *v1alpha1.VCluster, opts v1.UpdateOptions) (result *v1alpha1.VCluster, err error) { + emptyResult := &v1alpha1.VCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceActionWithOptions(vclustersResource, "status", vCluster, opts), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.VCluster), err +} + +// Delete takes name of the vCluster and deletes it. Returns an error if one occurs. +func (c *FakeVClusters) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteActionWithOptions(vclustersResource, name, opts), &v1alpha1.VCluster{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeVClusters) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewRootDeleteCollectionActionWithOptions(vclustersResource, opts, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.VClusterList{}) + return err +} + +// Patch applies the patch and returns the patched vCluster. +func (c *FakeVClusters) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.VCluster, err error) { + emptyResult := &v1alpha1.VCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceActionWithOptions(vclustersResource, name, pt, data, opts, subresources...), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.VCluster), err +} + +// Apply takes the given apply declarative configuration, applies it and returns the applied vCluster. +func (c *FakeVClusters) Apply(ctx context.Context, vCluster *mountsv1alpha1.VClusterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.VCluster, err error) { + if vCluster == nil { + return nil, fmt.Errorf("vCluster provided to Apply must not be nil") + } + data, err := json.Marshal(vCluster) + if err != nil { + return nil, err + } + name := vCluster.Name + if name == nil { + return nil, fmt.Errorf("vCluster.Name must be provided to Apply") + } + emptyResult := &v1alpha1.VCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceActionWithOptions(vclustersResource, *name, types.ApplyPatchType, data, opts.ToPatchOptions()), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.VCluster), err +} + +// ApplyStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). +func (c *FakeVClusters) ApplyStatus(ctx context.Context, vCluster *mountsv1alpha1.VClusterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.VCluster, err error) { + if vCluster == nil { + return nil, fmt.Errorf("vCluster provided to Apply must not be nil") + } + data, err := json.Marshal(vCluster) + if err != nil { + return nil, err + } + name := vCluster.Name + if name == nil { + return nil, fmt.Errorf("vCluster.Name must be provided to Apply") + } + emptyResult := &v1alpha1.VCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceActionWithOptions(vclustersResource, *name, types.ApplyPatchType, data, opts.ToPatchOptions(), "status"), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.VCluster), err +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/generated_expansion.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/generated_expansion.go new file mode 100644 index 00000000000..bfaf7b9ba75 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/generated_expansion.go @@ -0,0 +1,23 @@ +/* +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 + +type KubeClusterExpansion interface{} + +type VClusterExpansion interface{} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/kubecluster.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/kubecluster.go new file mode 100644 index 00000000000..798b7e674e1 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/kubecluster.go @@ -0,0 +1,74 @@ +/* +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" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + gentype "k8s.io/client-go/gentype" + + v1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1" + scheme "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/scheme" +) + +// KubeClustersGetter has a method to return a KubeClusterInterface. +// A group's client should implement this interface. +type KubeClustersGetter interface { + KubeClusters() KubeClusterInterface +} + +// KubeClusterInterface has methods to work with KubeCluster resources. +type KubeClusterInterface interface { + Create(ctx context.Context, kubeCluster *v1alpha1.KubeCluster, opts v1.CreateOptions) (*v1alpha1.KubeCluster, error) + Update(ctx context.Context, kubeCluster *v1alpha1.KubeCluster, opts v1.UpdateOptions) (*v1alpha1.KubeCluster, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + UpdateStatus(ctx context.Context, kubeCluster *v1alpha1.KubeCluster, opts v1.UpdateOptions) (*v1alpha1.KubeCluster, 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.KubeCluster, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.KubeClusterList, 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.KubeCluster, err error) + Apply(ctx context.Context, kubeCluster *mountsv1alpha1.KubeClusterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.KubeCluster, err error) + // Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). + ApplyStatus(ctx context.Context, kubeCluster *mountsv1alpha1.KubeClusterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.KubeCluster, err error) + KubeClusterExpansion +} + +// kubeClusters implements KubeClusterInterface +type kubeClusters struct { + *gentype.ClientWithListAndApply[*v1alpha1.KubeCluster, *v1alpha1.KubeClusterList, *mountsv1alpha1.KubeClusterApplyConfiguration] +} + +// newKubeClusters returns a KubeClusters +func newKubeClusters(c *MountsV1alpha1Client) *kubeClusters { + return &kubeClusters{ + gentype.NewClientWithListAndApply[*v1alpha1.KubeCluster, *v1alpha1.KubeClusterList, *mountsv1alpha1.KubeClusterApplyConfiguration]( + "kubeclusters", + c.RESTClient(), + scheme.ParameterCodec, + "", + func() *v1alpha1.KubeCluster { return &v1alpha1.KubeCluster{} }, + func() *v1alpha1.KubeClusterList { return &v1alpha1.KubeClusterList{} }), + } +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/mounts_client.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/mounts_client.go new file mode 100644 index 00000000000..f8047032fae --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/mounts_client.go @@ -0,0 +1,113 @@ +/* +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 ( + "net/http" + + rest "k8s.io/client-go/rest" + + v1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/scheme" +) + +type MountsV1alpha1Interface interface { + RESTClient() rest.Interface + KubeClustersGetter + VClustersGetter +} + +// MountsV1alpha1Client is used to interact with features provided by the mounts.contrib.kcp.io group. +type MountsV1alpha1Client struct { + restClient rest.Interface +} + +func (c *MountsV1alpha1Client) KubeClusters() KubeClusterInterface { + return newKubeClusters(c) +} + +func (c *MountsV1alpha1Client) VClusters() VClusterInterface { + return newVClusters(c) +} + +// NewForConfig creates a new MountsV1alpha1Client for the given config. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*MountsV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + httpClient, err := rest.HTTPClientFor(&config) + if err != nil { + return nil, err + } + return NewForConfigAndClient(&config, httpClient) +} + +// NewForConfigAndClient creates a new MountsV1alpha1Client for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +func NewForConfigAndClient(c *rest.Config, h *http.Client) (*MountsV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientForConfigAndClient(&config, h) + if err != nil { + return nil, err + } + return &MountsV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new MountsV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *MountsV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new MountsV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *MountsV1alpha1Client { + return &MountsV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *MountsV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/vcluster.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/vcluster.go new file mode 100644 index 00000000000..347b9afc468 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1/vcluster.go @@ -0,0 +1,74 @@ +/* +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" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + gentype "k8s.io/client-go/gentype" + + v1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/mounts/v1alpha1" + scheme "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/scheme" +) + +// VClustersGetter has a method to return a VClusterInterface. +// A group's client should implement this interface. +type VClustersGetter interface { + VClusters() VClusterInterface +} + +// VClusterInterface has methods to work with VCluster resources. +type VClusterInterface interface { + Create(ctx context.Context, vCluster *v1alpha1.VCluster, opts v1.CreateOptions) (*v1alpha1.VCluster, error) + Update(ctx context.Context, vCluster *v1alpha1.VCluster, opts v1.UpdateOptions) (*v1alpha1.VCluster, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + UpdateStatus(ctx context.Context, vCluster *v1alpha1.VCluster, opts v1.UpdateOptions) (*v1alpha1.VCluster, 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.VCluster, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.VClusterList, 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.VCluster, err error) + Apply(ctx context.Context, vCluster *mountsv1alpha1.VClusterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.VCluster, err error) + // Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). + ApplyStatus(ctx context.Context, vCluster *mountsv1alpha1.VClusterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.VCluster, err error) + VClusterExpansion +} + +// vClusters implements VClusterInterface +type vClusters struct { + *gentype.ClientWithListAndApply[*v1alpha1.VCluster, *v1alpha1.VClusterList, *mountsv1alpha1.VClusterApplyConfiguration] +} + +// newVClusters returns a VClusters +func newVClusters(c *MountsV1alpha1Client) *vClusters { + return &vClusters{ + gentype.NewClientWithListAndApply[*v1alpha1.VCluster, *v1alpha1.VClusterList, *mountsv1alpha1.VClusterApplyConfiguration]( + "vclusters", + c.RESTClient(), + scheme.ParameterCodec, + "", + func() *v1alpha1.VCluster { return &v1alpha1.VCluster{} }, + func() *v1alpha1.VClusterList { return &v1alpha1.VClusterList{} }), + } +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/doc.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/doc.go new file mode 100644 index 00000000000..364b93c7cfd --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/doc.go @@ -0,0 +1,20 @@ +/* +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. + +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/fake/doc.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/fake/doc.go new file mode 100644 index 00000000000..e388f29189e --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/fake/doc.go @@ -0,0 +1,20 @@ +/* +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 has the automatically generated clients. +package fake diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/fake/fake_targetkubecluster.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/fake/fake_targetkubecluster.go new file mode 100644 index 00000000000..af42b7911cf --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/fake/fake_targetkubecluster.go @@ -0,0 +1,187 @@ +/* +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" + json "encoding/json" + "fmt" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + + v1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1" +) + +// FakeTargetKubeClusters implements TargetKubeClusterInterface +type FakeTargetKubeClusters struct { + Fake *FakeTargetsV1alpha1 +} + +var targetkubeclustersResource = v1alpha1.SchemeGroupVersion.WithResource("targetkubeclusters") + +var targetkubeclustersKind = v1alpha1.SchemeGroupVersion.WithKind("TargetKubeCluster") + +// Get takes name of the targetKubeCluster, and returns the corresponding targetKubeCluster object, and an error if there is any. +func (c *FakeTargetKubeClusters) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.TargetKubeCluster, err error) { + emptyResult := &v1alpha1.TargetKubeCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootGetActionWithOptions(targetkubeclustersResource, name, options), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.TargetKubeCluster), err +} + +// List takes label and field selectors, and returns the list of TargetKubeClusters that match those selectors. +func (c *FakeTargetKubeClusters) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.TargetKubeClusterList, err error) { + emptyResult := &v1alpha1.TargetKubeClusterList{} + obj, err := c.Fake. + Invokes(testing.NewRootListActionWithOptions(targetkubeclustersResource, targetkubeclustersKind, opts), emptyResult) + if obj == nil { + return emptyResult, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.TargetKubeClusterList{ListMeta: obj.(*v1alpha1.TargetKubeClusterList).ListMeta} + for _, item := range obj.(*v1alpha1.TargetKubeClusterList).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 targetKubeClusters. +func (c *FakeTargetKubeClusters) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchActionWithOptions(targetkubeclustersResource, opts)) +} + +// Create takes the representation of a targetKubeCluster and creates it. Returns the server's representation of the targetKubeCluster, and an error, if there is any. +func (c *FakeTargetKubeClusters) Create(ctx context.Context, targetKubeCluster *v1alpha1.TargetKubeCluster, opts v1.CreateOptions) (result *v1alpha1.TargetKubeCluster, err error) { + emptyResult := &v1alpha1.TargetKubeCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootCreateActionWithOptions(targetkubeclustersResource, targetKubeCluster, opts), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.TargetKubeCluster), err +} + +// Update takes the representation of a targetKubeCluster and updates it. Returns the server's representation of the targetKubeCluster, and an error, if there is any. +func (c *FakeTargetKubeClusters) Update(ctx context.Context, targetKubeCluster *v1alpha1.TargetKubeCluster, opts v1.UpdateOptions) (result *v1alpha1.TargetKubeCluster, err error) { + emptyResult := &v1alpha1.TargetKubeCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootUpdateActionWithOptions(targetkubeclustersResource, targetKubeCluster, opts), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.TargetKubeCluster), 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 *FakeTargetKubeClusters) UpdateStatus(ctx context.Context, targetKubeCluster *v1alpha1.TargetKubeCluster, opts v1.UpdateOptions) (result *v1alpha1.TargetKubeCluster, err error) { + emptyResult := &v1alpha1.TargetKubeCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceActionWithOptions(targetkubeclustersResource, "status", targetKubeCluster, opts), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.TargetKubeCluster), err +} + +// Delete takes name of the targetKubeCluster and deletes it. Returns an error if one occurs. +func (c *FakeTargetKubeClusters) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteActionWithOptions(targetkubeclustersResource, name, opts), &v1alpha1.TargetKubeCluster{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeTargetKubeClusters) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewRootDeleteCollectionActionWithOptions(targetkubeclustersResource, opts, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.TargetKubeClusterList{}) + return err +} + +// Patch applies the patch and returns the patched targetKubeCluster. +func (c *FakeTargetKubeClusters) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.TargetKubeCluster, err error) { + emptyResult := &v1alpha1.TargetKubeCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceActionWithOptions(targetkubeclustersResource, name, pt, data, opts, subresources...), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.TargetKubeCluster), err +} + +// Apply takes the given apply declarative configuration, applies it and returns the applied targetKubeCluster. +func (c *FakeTargetKubeClusters) Apply(ctx context.Context, targetKubeCluster *targetsv1alpha1.TargetKubeClusterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.TargetKubeCluster, err error) { + if targetKubeCluster == nil { + return nil, fmt.Errorf("targetKubeCluster provided to Apply must not be nil") + } + data, err := json.Marshal(targetKubeCluster) + if err != nil { + return nil, err + } + name := targetKubeCluster.Name + if name == nil { + return nil, fmt.Errorf("targetKubeCluster.Name must be provided to Apply") + } + emptyResult := &v1alpha1.TargetKubeCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceActionWithOptions(targetkubeclustersResource, *name, types.ApplyPatchType, data, opts.ToPatchOptions()), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.TargetKubeCluster), err +} + +// ApplyStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). +func (c *FakeTargetKubeClusters) ApplyStatus(ctx context.Context, targetKubeCluster *targetsv1alpha1.TargetKubeClusterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.TargetKubeCluster, err error) { + if targetKubeCluster == nil { + return nil, fmt.Errorf("targetKubeCluster provided to Apply must not be nil") + } + data, err := json.Marshal(targetKubeCluster) + if err != nil { + return nil, err + } + name := targetKubeCluster.Name + if name == nil { + return nil, fmt.Errorf("targetKubeCluster.Name must be provided to Apply") + } + emptyResult := &v1alpha1.TargetKubeCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceActionWithOptions(targetkubeclustersResource, *name, types.ApplyPatchType, data, opts.ToPatchOptions(), "status"), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.TargetKubeCluster), err +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/fake/fake_targets_client.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/fake/fake_targets_client.go new file mode 100644 index 00000000000..8d27340f656 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/fake/fake_targets_client.go @@ -0,0 +1,45 @@ +/* +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 ( + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" + + v1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1" +) + +type FakeTargetsV1alpha1 struct { + *testing.Fake +} + +func (c *FakeTargetsV1alpha1) TargetKubeClusters() v1alpha1.TargetKubeClusterInterface { + return &FakeTargetKubeClusters{c} +} + +func (c *FakeTargetsV1alpha1) TargetVClusters() v1alpha1.TargetVClusterInterface { + return &FakeTargetVClusters{c} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeTargetsV1alpha1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/fake/fake_targetvcluster.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/fake/fake_targetvcluster.go new file mode 100644 index 00000000000..2d6bfc51631 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/fake/fake_targetvcluster.go @@ -0,0 +1,187 @@ +/* +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" + json "encoding/json" + "fmt" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + + v1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1" +) + +// FakeTargetVClusters implements TargetVClusterInterface +type FakeTargetVClusters struct { + Fake *FakeTargetsV1alpha1 +} + +var targetvclustersResource = v1alpha1.SchemeGroupVersion.WithResource("targetvclusters") + +var targetvclustersKind = v1alpha1.SchemeGroupVersion.WithKind("TargetVCluster") + +// Get takes name of the targetVCluster, and returns the corresponding targetVCluster object, and an error if there is any. +func (c *FakeTargetVClusters) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.TargetVCluster, err error) { + emptyResult := &v1alpha1.TargetVCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootGetActionWithOptions(targetvclustersResource, name, options), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.TargetVCluster), err +} + +// List takes label and field selectors, and returns the list of TargetVClusters that match those selectors. +func (c *FakeTargetVClusters) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.TargetVClusterList, err error) { + emptyResult := &v1alpha1.TargetVClusterList{} + obj, err := c.Fake. + Invokes(testing.NewRootListActionWithOptions(targetvclustersResource, targetvclustersKind, opts), emptyResult) + if obj == nil { + return emptyResult, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.TargetVClusterList{ListMeta: obj.(*v1alpha1.TargetVClusterList).ListMeta} + for _, item := range obj.(*v1alpha1.TargetVClusterList).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 targetVClusters. +func (c *FakeTargetVClusters) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchActionWithOptions(targetvclustersResource, opts)) +} + +// Create takes the representation of a targetVCluster and creates it. Returns the server's representation of the targetVCluster, and an error, if there is any. +func (c *FakeTargetVClusters) Create(ctx context.Context, targetVCluster *v1alpha1.TargetVCluster, opts v1.CreateOptions) (result *v1alpha1.TargetVCluster, err error) { + emptyResult := &v1alpha1.TargetVCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootCreateActionWithOptions(targetvclustersResource, targetVCluster, opts), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.TargetVCluster), err +} + +// Update takes the representation of a targetVCluster and updates it. Returns the server's representation of the targetVCluster, and an error, if there is any. +func (c *FakeTargetVClusters) Update(ctx context.Context, targetVCluster *v1alpha1.TargetVCluster, opts v1.UpdateOptions) (result *v1alpha1.TargetVCluster, err error) { + emptyResult := &v1alpha1.TargetVCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootUpdateActionWithOptions(targetvclustersResource, targetVCluster, opts), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.TargetVCluster), 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 *FakeTargetVClusters) UpdateStatus(ctx context.Context, targetVCluster *v1alpha1.TargetVCluster, opts v1.UpdateOptions) (result *v1alpha1.TargetVCluster, err error) { + emptyResult := &v1alpha1.TargetVCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceActionWithOptions(targetvclustersResource, "status", targetVCluster, opts), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.TargetVCluster), err +} + +// Delete takes name of the targetVCluster and deletes it. Returns an error if one occurs. +func (c *FakeTargetVClusters) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteActionWithOptions(targetvclustersResource, name, opts), &v1alpha1.TargetVCluster{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeTargetVClusters) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewRootDeleteCollectionActionWithOptions(targetvclustersResource, opts, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.TargetVClusterList{}) + return err +} + +// Patch applies the patch and returns the patched targetVCluster. +func (c *FakeTargetVClusters) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.TargetVCluster, err error) { + emptyResult := &v1alpha1.TargetVCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceActionWithOptions(targetvclustersResource, name, pt, data, opts, subresources...), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.TargetVCluster), err +} + +// Apply takes the given apply declarative configuration, applies it and returns the applied targetVCluster. +func (c *FakeTargetVClusters) Apply(ctx context.Context, targetVCluster *targetsv1alpha1.TargetVClusterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.TargetVCluster, err error) { + if targetVCluster == nil { + return nil, fmt.Errorf("targetVCluster provided to Apply must not be nil") + } + data, err := json.Marshal(targetVCluster) + if err != nil { + return nil, err + } + name := targetVCluster.Name + if name == nil { + return nil, fmt.Errorf("targetVCluster.Name must be provided to Apply") + } + emptyResult := &v1alpha1.TargetVCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceActionWithOptions(targetvclustersResource, *name, types.ApplyPatchType, data, opts.ToPatchOptions()), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.TargetVCluster), err +} + +// ApplyStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). +func (c *FakeTargetVClusters) ApplyStatus(ctx context.Context, targetVCluster *targetsv1alpha1.TargetVClusterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.TargetVCluster, err error) { + if targetVCluster == nil { + return nil, fmt.Errorf("targetVCluster provided to Apply must not be nil") + } + data, err := json.Marshal(targetVCluster) + if err != nil { + return nil, err + } + name := targetVCluster.Name + if name == nil { + return nil, fmt.Errorf("targetVCluster.Name must be provided to Apply") + } + emptyResult := &v1alpha1.TargetVCluster{} + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceActionWithOptions(targetvclustersResource, *name, types.ApplyPatchType, data, opts.ToPatchOptions(), "status"), emptyResult) + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.TargetVCluster), err +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/generated_expansion.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/generated_expansion.go new file mode 100644 index 00000000000..34425eb7bc3 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/generated_expansion.go @@ -0,0 +1,23 @@ +/* +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 + +type TargetKubeClusterExpansion interface{} + +type TargetVClusterExpansion interface{} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/targetkubecluster.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/targetkubecluster.go new file mode 100644 index 00000000000..6eebca81a31 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/targetkubecluster.go @@ -0,0 +1,74 @@ +/* +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" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + gentype "k8s.io/client-go/gentype" + + v1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1" + scheme "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/scheme" +) + +// TargetKubeClustersGetter has a method to return a TargetKubeClusterInterface. +// A group's client should implement this interface. +type TargetKubeClustersGetter interface { + TargetKubeClusters() TargetKubeClusterInterface +} + +// TargetKubeClusterInterface has methods to work with TargetKubeCluster resources. +type TargetKubeClusterInterface interface { + Create(ctx context.Context, targetKubeCluster *v1alpha1.TargetKubeCluster, opts v1.CreateOptions) (*v1alpha1.TargetKubeCluster, error) + Update(ctx context.Context, targetKubeCluster *v1alpha1.TargetKubeCluster, opts v1.UpdateOptions) (*v1alpha1.TargetKubeCluster, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + UpdateStatus(ctx context.Context, targetKubeCluster *v1alpha1.TargetKubeCluster, opts v1.UpdateOptions) (*v1alpha1.TargetKubeCluster, 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.TargetKubeCluster, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.TargetKubeClusterList, 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.TargetKubeCluster, err error) + Apply(ctx context.Context, targetKubeCluster *targetsv1alpha1.TargetKubeClusterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.TargetKubeCluster, err error) + // Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). + ApplyStatus(ctx context.Context, targetKubeCluster *targetsv1alpha1.TargetKubeClusterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.TargetKubeCluster, err error) + TargetKubeClusterExpansion +} + +// targetKubeClusters implements TargetKubeClusterInterface +type targetKubeClusters struct { + *gentype.ClientWithListAndApply[*v1alpha1.TargetKubeCluster, *v1alpha1.TargetKubeClusterList, *targetsv1alpha1.TargetKubeClusterApplyConfiguration] +} + +// newTargetKubeClusters returns a TargetKubeClusters +func newTargetKubeClusters(c *TargetsV1alpha1Client) *targetKubeClusters { + return &targetKubeClusters{ + gentype.NewClientWithListAndApply[*v1alpha1.TargetKubeCluster, *v1alpha1.TargetKubeClusterList, *targetsv1alpha1.TargetKubeClusterApplyConfiguration]( + "targetkubeclusters", + c.RESTClient(), + scheme.ParameterCodec, + "", + func() *v1alpha1.TargetKubeCluster { return &v1alpha1.TargetKubeCluster{} }, + func() *v1alpha1.TargetKubeClusterList { return &v1alpha1.TargetKubeClusterList{} }), + } +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/targets_client.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/targets_client.go new file mode 100644 index 00000000000..0f68798ecb2 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/targets_client.go @@ -0,0 +1,113 @@ +/* +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 ( + "net/http" + + rest "k8s.io/client-go/rest" + + v1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/scheme" +) + +type TargetsV1alpha1Interface interface { + RESTClient() rest.Interface + TargetKubeClustersGetter + TargetVClustersGetter +} + +// TargetsV1alpha1Client is used to interact with features provided by the targets.contrib.kcp.io group. +type TargetsV1alpha1Client struct { + restClient rest.Interface +} + +func (c *TargetsV1alpha1Client) TargetKubeClusters() TargetKubeClusterInterface { + return newTargetKubeClusters(c) +} + +func (c *TargetsV1alpha1Client) TargetVClusters() TargetVClusterInterface { + return newTargetVClusters(c) +} + +// NewForConfig creates a new TargetsV1alpha1Client for the given config. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*TargetsV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + httpClient, err := rest.HTTPClientFor(&config) + if err != nil { + return nil, err + } + return NewForConfigAndClient(&config, httpClient) +} + +// NewForConfigAndClient creates a new TargetsV1alpha1Client for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +func NewForConfigAndClient(c *rest.Config, h *http.Client) (*TargetsV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientForConfigAndClient(&config, h) + if err != nil { + return nil, err + } + return &TargetsV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new TargetsV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *TargetsV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new TargetsV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *TargetsV1alpha1Client { + return &TargetsV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *TargetsV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/targetvcluster.go b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/targetvcluster.go new file mode 100644 index 00000000000..ec6fd7b3a21 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1/targetvcluster.go @@ -0,0 +1,74 @@ +/* +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" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + gentype "k8s.io/client-go/gentype" + + v1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration/targets/v1alpha1" + scheme "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/scheme" +) + +// TargetVClustersGetter has a method to return a TargetVClusterInterface. +// A group's client should implement this interface. +type TargetVClustersGetter interface { + TargetVClusters() TargetVClusterInterface +} + +// TargetVClusterInterface has methods to work with TargetVCluster resources. +type TargetVClusterInterface interface { + Create(ctx context.Context, targetVCluster *v1alpha1.TargetVCluster, opts v1.CreateOptions) (*v1alpha1.TargetVCluster, error) + Update(ctx context.Context, targetVCluster *v1alpha1.TargetVCluster, opts v1.UpdateOptions) (*v1alpha1.TargetVCluster, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + UpdateStatus(ctx context.Context, targetVCluster *v1alpha1.TargetVCluster, opts v1.UpdateOptions) (*v1alpha1.TargetVCluster, 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.TargetVCluster, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.TargetVClusterList, 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.TargetVCluster, err error) + Apply(ctx context.Context, targetVCluster *targetsv1alpha1.TargetVClusterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.TargetVCluster, err error) + // Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). + ApplyStatus(ctx context.Context, targetVCluster *targetsv1alpha1.TargetVClusterApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.TargetVCluster, err error) + TargetVClusterExpansion +} + +// targetVClusters implements TargetVClusterInterface +type targetVClusters struct { + *gentype.ClientWithListAndApply[*v1alpha1.TargetVCluster, *v1alpha1.TargetVClusterList, *targetsv1alpha1.TargetVClusterApplyConfiguration] +} + +// newTargetVClusters returns a TargetVClusters +func newTargetVClusters(c *TargetsV1alpha1Client) *targetVClusters { + return &targetVClusters{ + gentype.NewClientWithListAndApply[*v1alpha1.TargetVCluster, *v1alpha1.TargetVClusterList, *targetsv1alpha1.TargetVClusterApplyConfiguration]( + "targetvclusters", + c.RESTClient(), + scheme.ParameterCodec, + "", + func() *v1alpha1.TargetVCluster { return &v1alpha1.TargetVCluster{} }, + func() *v1alpha1.TargetVClusterList { return &v1alpha1.TargetVClusterList{} }), + } +} diff --git a/contrib/mounts-virtualworkspace/client/informers/externalversions/factory.go b/contrib/mounts-virtualworkspace/client/informers/externalversions/factory.go new file mode 100644 index 00000000000..8fd93d58fd2 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/informers/externalversions/factory.go @@ -0,0 +1,426 @@ +//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 informers + +import ( + "reflect" + "sync" + "time" + + kcpcache "github.com/kcp-dev/apimachinery/v2/pkg/cache" + "github.com/kcp-dev/logicalcluster/v3" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/tools/cache" + + scopedclientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned" + clientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions/internalinterfaces" + mountsinformers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions/mounts" + targetsinformers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions/targets" +) + +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*SharedInformerOptions) *SharedInformerOptions + +type SharedInformerOptions struct { + customResync map[reflect.Type]time.Duration + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +type sharedInformerFactory struct { + client clientset.ClusterInterface + tweakListOptions internalinterfaces.TweakListOptionsFunc + lock sync.Mutex + defaultResync time.Duration + customResync map[reflect.Type]time.Duration + + informers map[reflect.Type]kcpcache.ScopeableSharedIndexInformer + // startedInformers is used for tracking which informers have been started. + // This allows Start() to be called multiple times safely. + startedInformers map[reflect.Type]bool + // wg tracks how many goroutines were started. + wg sync.WaitGroup + // shuttingDown is true when Shutdown has been called. It may still be running + // because it needs to wait for goroutines. + shuttingDown bool +} + +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[metav1.Object]time.Duration) SharedInformerOption { + return func(opts *SharedInformerOptions) *SharedInformerOptions { + for k, v := range resyncConfig { + opts.customResync[reflect.TypeOf(k)] = v + } + return opts + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(opts *SharedInformerOptions) *SharedInformerOptions { + opts.tweakListOptions = tweakListOptions + return opts + } +} + +// NewSharedInformerFactory constructs a new instance of SharedInformerFactory for all namespaces. +func NewSharedInformerFactory(client clientset.ClusterInterface, defaultResync time.Duration) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client clientset.ClusterInterface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ + client: client, + defaultResync: defaultResync, + informers: make(map[reflect.Type]kcpcache.ScopeableSharedIndexInformer), + startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + opts := &SharedInformerOptions{ + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + opts = opt(opts) + } + + // Forward options to the factory + factory.customResync = opts.customResync + factory.tweakListOptions = opts.tweakListOptions + + return factory +} + +// Start initializes all requested informers. +func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { + f.lock.Lock() + defer f.lock.Unlock() + + if f.shuttingDown { + return + } + + for informerType, informer := range f.informers { + if !f.startedInformers[informerType] { + f.wg.Add(1) + // We need a new variable in each loop iteration, + // otherwise the goroutine would use the loop variable + // and that keeps changing. + informer := informer + go func() { + defer f.wg.Done() + informer.Run(stopCh) + }() + f.startedInformers[informerType] = true + } + } +} + +func (f *sharedInformerFactory) Shutdown() { + f.lock.Lock() + f.shuttingDown = true + f.lock.Unlock() + + // Will return immediately if there is nothing to wait for. + f.wg.Wait() +} + +// WaitForCacheSync waits for all started informers' cache were synced. +func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { + informers := func() map[reflect.Type]kcpcache.ScopeableSharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informers := map[reflect.Type]kcpcache.ScopeableSharedIndexInformer{} + for informerType, informer := range f.informers { + if f.startedInformers[informerType] { + informers[informerType] = informer + } + } + return informers + }() + + res := map[reflect.Type]bool{} + for informType, informer := range informers { + res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) + } + return res +} + +// InformerFor returns the SharedIndexInformer for obj. +func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) kcpcache.ScopeableSharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informerType := reflect.TypeOf(obj) + informer, exists := f.informers[informerType] + if exists { + return informer + } + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) + f.informers[informerType] = informer + + return informer +} + +type ScopedDynamicSharedInformerFactory interface { + // ForResource gives generic access to a shared informer of the matching type. + ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + + // Start initializes all requested informers. They are handled in goroutines + // which run until the stop channel gets closed. + Start(stopCh <-chan struct{}) +} + +// SharedInformerFactory provides shared informers for resources in all known +// API group versions. +// +// It is typically used like this: +// +// ctx, cancel := context.Background() +// defer cancel() +// factory := NewSharedInformerFactoryWithOptions(client, resyncPeriod) +// defer factory.Shutdown() // Returns immediately if nothing was started. +// genericInformer := factory.ForResource(resource) +// typedInformer := factory.SomeAPIGroup().V1().SomeType() +// factory.Start(ctx.Done()) // Start processing these informers. +// synced := factory.WaitForCacheSync(ctx.Done()) +// for v, ok := range synced { +// if !ok { +// fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v) +// return +// } +// } +// +// // Creating informers can also be created after Start, but then +// // Start must be called again: +// anotherGenericInformer := factory.ForResource(resource) +// factory.Start(ctx.Done()) +type SharedInformerFactory interface { + internalinterfaces.SharedInformerFactory + + Cluster(logicalcluster.Name) ScopedDynamicSharedInformerFactory + + // Start initializes all requested informers. They are handled in goroutines + // which run until the stop channel gets closed. + Start(stopCh <-chan struct{}) + + // Shutdown marks a factory as shutting down. At that point no new + // informers can be started anymore and Start will return without + // doing anything. + // + // In addition, Shutdown blocks until all goroutines have terminated. For that + // to happen, the close channel(s) that they were started with must be closed, + // either before Shutdown gets called or while it is waiting. + // + // Shutdown may be called multiple times, even concurrently. All such calls will + // block until all goroutines have terminated. + Shutdown() + + // ForResource gives generic access to a shared informer of the matching type. + ForResource(resource schema.GroupVersionResource) (GenericClusterInformer, error) + + // WaitForCacheSync blocks until all started informers' caches were synced + // or the stop channel gets closed. + WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + + // InformerFor returns the SharedIndexInformer for obj. + InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) kcpcache.ScopeableSharedIndexInformer + + Mounts() mountsinformers.ClusterInterface + Targets() targetsinformers.ClusterInterface +} + +func (f *sharedInformerFactory) Mounts() mountsinformers.ClusterInterface { + return mountsinformers.New(f, f.tweakListOptions) +} + +func (f *sharedInformerFactory) Targets() targetsinformers.ClusterInterface { + return targetsinformers.New(f, f.tweakListOptions) +} + +func (f *sharedInformerFactory) Cluster(clusterName logicalcluster.Name) ScopedDynamicSharedInformerFactory { + return &scopedDynamicSharedInformerFactory{ + sharedInformerFactory: f, + clusterName: clusterName, + } +} + +type scopedDynamicSharedInformerFactory struct { + *sharedInformerFactory + clusterName logicalcluster.Name +} + +func (f *scopedDynamicSharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { + clusterInformer, err := f.sharedInformerFactory.ForResource(resource) + if err != nil { + return nil, err + } + return clusterInformer.Cluster(f.clusterName), nil +} + +func (f *scopedDynamicSharedInformerFactory) Start(stopCh <-chan struct{}) { + f.sharedInformerFactory.Start(stopCh) +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(opts *SharedInformerOptions) *SharedInformerOptions { + opts.namespace = namespace + return opts + } +} + +type sharedScopedInformerFactory struct { + client scopedclientset.Interface + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc + lock sync.Mutex + defaultResync time.Duration + customResync map[reflect.Type]time.Duration + + informers map[reflect.Type]cache.SharedIndexInformer + // startedInformers is used for tracking which informers have been started. + // This allows Start() to be called multiple times safely. + startedInformers map[reflect.Type]bool +} + +// NewSharedScopedInformerFactory constructs a new instance of SharedInformerFactory for some or all namespaces. +func NewSharedScopedInformerFactory(client scopedclientset.Interface, defaultResync time.Duration, namespace string) SharedScopedInformerFactory { + return NewSharedScopedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace)) +} + +// NewSharedScopedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedScopedInformerFactoryWithOptions(client scopedclientset.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedScopedInformerFactory { + factory := &sharedScopedInformerFactory{ + client: client, + defaultResync: defaultResync, + informers: make(map[reflect.Type]cache.SharedIndexInformer), + startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + opts := &SharedInformerOptions{ + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + opts = opt(opts) + } + + // Forward options to the factory + factory.customResync = opts.customResync + factory.tweakListOptions = opts.tweakListOptions + factory.namespace = opts.namespace + + return factory +} + +// Start initializes all requested informers. +func (f *sharedScopedInformerFactory) Start(stopCh <-chan struct{}) { + f.lock.Lock() + defer f.lock.Unlock() + + for informerType, informer := range f.informers { + if !f.startedInformers[informerType] { + go informer.Run(stopCh) + f.startedInformers[informerType] = true + } + } +} + +// WaitForCacheSync waits for all started informers' cache were synced. +func (f *sharedScopedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { + informers := func() map[reflect.Type]cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informers := map[reflect.Type]cache.SharedIndexInformer{} + for informerType, informer := range f.informers { + if f.startedInformers[informerType] { + informers[informerType] = informer + } + } + return informers + }() + + res := map[reflect.Type]bool{} + for informType, informer := range informers { + res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) + } + return res +} + +// InformerFor returns the SharedIndexInformer for obj. +func (f *sharedScopedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewScopedInformerFunc) cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informerType := reflect.TypeOf(obj) + informer, exists := f.informers[informerType] + if exists { + return informer + } + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) + f.informers[informerType] = informer + + return informer +} + +// SharedScopedInformerFactory provides shared informers for resources in all known +// API group versions, scoped to one workspace. +type SharedScopedInformerFactory interface { + internalinterfaces.SharedScopedInformerFactory + ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + + Mounts() mountsinformers.Interface + Targets() targetsinformers.Interface +} + +func (f *sharedScopedInformerFactory) Mounts() mountsinformers.Interface { + return mountsinformers.NewScoped(f, f.namespace, f.tweakListOptions) +} + +func (f *sharedScopedInformerFactory) Targets() targetsinformers.Interface { + return targetsinformers.NewScoped(f, f.namespace, f.tweakListOptions) +} diff --git a/contrib/mounts-virtualworkspace/client/informers/externalversions/generic.go b/contrib/mounts-virtualworkspace/client/informers/externalversions/generic.go new file mode 100644 index 00000000000..374c73d3642 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/informers/externalversions/generic.go @@ -0,0 +1,126 @@ +//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 informers + +import ( + "fmt" + + kcpcache "github.com/kcp-dev/apimachinery/v2/pkg/cache" + "github.com/kcp-dev/logicalcluster/v3" + + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/tools/cache" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" +) + +type GenericClusterInformer interface { + Cluster(logicalcluster.Name) GenericInformer + Informer() kcpcache.ScopeableSharedIndexInformer + Lister() kcpcache.GenericClusterLister +} + +type GenericInformer interface { + Informer() cache.SharedIndexInformer + Lister() cache.GenericLister +} + +type genericClusterInformer struct { + informer kcpcache.ScopeableSharedIndexInformer + resource schema.GroupResource +} + +// Informer returns the SharedIndexInformer. +func (f *genericClusterInformer) Informer() kcpcache.ScopeableSharedIndexInformer { + return f.informer +} + +// Lister returns the GenericClusterLister. +func (f *genericClusterInformer) Lister() kcpcache.GenericClusterLister { + return kcpcache.NewGenericClusterLister(f.Informer().GetIndexer(), f.resource) +} + +// Cluster scopes to a GenericInformer. +func (f *genericClusterInformer) Cluster(clusterName logicalcluster.Name) GenericInformer { + return &genericInformer{ + informer: f.Informer().Cluster(clusterName), + lister: f.Lister().ByCluster(clusterName), + } +} + +type genericInformer struct { + informer cache.SharedIndexInformer + lister cache.GenericLister +} + +// Informer returns the SharedIndexInformer. +func (f *genericInformer) Informer() cache.SharedIndexInformer { + return f.informer +} + +// Lister returns the GenericLister. +func (f *genericInformer) Lister() cache.GenericLister { + return f.lister +} + +// ForResource gives generic access to a shared informer of the matching type +// TODO extend this to unknown resources with a client pool +func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericClusterInformer, error) { + switch resource { + // Group=mounts.contrib.kcp.io, Version=V1alpha1 + case mountsv1alpha1.SchemeGroupVersion.WithResource("kubeclusters"): + return &genericClusterInformer{resource: resource.GroupResource(), informer: f.Mounts().V1alpha1().KubeClusters().Informer()}, nil + case mountsv1alpha1.SchemeGroupVersion.WithResource("vclusters"): + return &genericClusterInformer{resource: resource.GroupResource(), informer: f.Mounts().V1alpha1().VClusters().Informer()}, nil + // Group=targets.contrib.kcp.io, Version=V1alpha1 + case targetsv1alpha1.SchemeGroupVersion.WithResource("targetkubeclusters"): + return &genericClusterInformer{resource: resource.GroupResource(), informer: f.Targets().V1alpha1().TargetKubeClusters().Informer()}, nil + case targetsv1alpha1.SchemeGroupVersion.WithResource("targetvclusters"): + return &genericClusterInformer{resource: resource.GroupResource(), informer: f.Targets().V1alpha1().TargetVClusters().Informer()}, nil + } + + return nil, fmt.Errorf("no informer found for %v", resource) +} + +// ForResource gives generic access to a shared informer of the matching type +// TODO extend this to unknown resources with a client pool +func (f *sharedScopedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { + switch resource { + // Group=mounts.contrib.kcp.io, Version=V1alpha1 + case mountsv1alpha1.SchemeGroupVersion.WithResource("kubeclusters"): + informer := f.Mounts().V1alpha1().KubeClusters().Informer() + return &genericInformer{lister: cache.NewGenericLister(informer.GetIndexer(), resource.GroupResource()), informer: informer}, nil + case mountsv1alpha1.SchemeGroupVersion.WithResource("vclusters"): + informer := f.Mounts().V1alpha1().VClusters().Informer() + return &genericInformer{lister: cache.NewGenericLister(informer.GetIndexer(), resource.GroupResource()), informer: informer}, nil + // Group=targets.contrib.kcp.io, Version=V1alpha1 + case targetsv1alpha1.SchemeGroupVersion.WithResource("targetkubeclusters"): + informer := f.Targets().V1alpha1().TargetKubeClusters().Informer() + return &genericInformer{lister: cache.NewGenericLister(informer.GetIndexer(), resource.GroupResource()), informer: informer}, nil + case targetsv1alpha1.SchemeGroupVersion.WithResource("targetvclusters"): + informer := f.Targets().V1alpha1().TargetVClusters().Informer() + return &genericInformer{lister: cache.NewGenericLister(informer.GetIndexer(), resource.GroupResource()), informer: informer}, nil + } + + return nil, fmt.Errorf("no informer found for %v", resource) +} diff --git a/contrib/mounts-virtualworkspace/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/contrib/mounts-virtualworkspace/client/informers/externalversions/internalinterfaces/factory_interfaces.go new file mode 100644 index 00000000000..f41975f9dc1 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -0,0 +1,56 @@ +//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 internalinterfaces + +import ( + time "time" + + kcpcache "github.com/kcp-dev/apimachinery/v2/pkg/cache" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/cache" + + scopedclientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned" + clientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster" +) + +// NewInformerFunc takes clientset.ClusterInterface and time.Duration to return a ScopeableSharedIndexInformer. +type NewInformerFunc func(clientset.ClusterInterface, time.Duration) kcpcache.ScopeableSharedIndexInformer + +// SharedInformerFactory a small interface to allow for adding an informer without an import cycle +type SharedInformerFactory interface { + Start(stopCh <-chan struct{}) + InformerFor(obj runtime.Object, newFunc NewInformerFunc) kcpcache.ScopeableSharedIndexInformer +} + +// NewScopedInformerFunc takes scopedclientset.Interface and time.Duration to return a SharedIndexInformer. +type NewScopedInformerFunc func(scopedclientset.Interface, time.Duration) cache.SharedIndexInformer + +// SharedScopedInformerFactory a small interface to allow for adding an informer without an import cycle +type SharedScopedInformerFactory interface { + Start(stopCh <-chan struct{}) + InformerFor(obj runtime.Object, newFunc NewScopedInformerFunc) cache.SharedIndexInformer +} + +// TweakListOptionsFunc is a function that transforms a metav1.ListOptions. +type TweakListOptionsFunc func(*metav1.ListOptions) diff --git a/contrib/mounts-virtualworkspace/client/informers/externalversions/mounts/interface.go b/contrib/mounts-virtualworkspace/client/informers/externalversions/mounts/interface.go new file mode 100644 index 00000000000..f9a8997b238 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/informers/externalversions/mounts/interface.go @@ -0,0 +1,68 @@ +//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 mounts + +import ( + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions/internalinterfaces" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions/mounts/v1alpha1" +) + +type ClusterInterface interface { + // V1alpha1 provides access to the shared informers in V1alpha1. + V1alpha1() v1alpha1.ClusterInterface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new ClusterInterface. +func New(f internalinterfaces.SharedInformerFactory, tweakListOptions internalinterfaces.TweakListOptionsFunc) ClusterInterface { + return &group{factory: f, tweakListOptions: tweakListOptions} +} + +// V1alpha1 returns a new v1alpha1.ClusterInterface. +func (g *group) V1alpha1() v1alpha1.ClusterInterface { + return v1alpha1.New(g.factory, g.tweakListOptions) +} + +type Interface interface { + // V1alpha1 provides access to the shared informers in V1alpha1. + V1alpha1() v1alpha1.Interface +} + +type scopedGroup struct { + factory internalinterfaces.SharedScopedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// New returns a new Interface. +func NewScoped(f internalinterfaces.SharedScopedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &scopedGroup{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// V1alpha1 returns a new v1alpha1.ClusterInterface. +func (g *scopedGroup) V1alpha1() v1alpha1.Interface { + return v1alpha1.NewScoped(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/contrib/mounts-virtualworkspace/client/informers/externalversions/mounts/v1alpha1/interface.go b/contrib/mounts-virtualworkspace/client/informers/externalversions/mounts/v1alpha1/interface.go new file mode 100644 index 00000000000..d65290783e0 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/informers/externalversions/mounts/v1alpha1/interface.go @@ -0,0 +1,81 @@ +//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 ( + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions/internalinterfaces" +) + +type ClusterInterface interface { + // KubeClusters returns a KubeClusterClusterInformer + KubeClusters() KubeClusterClusterInformer + // VClusters returns a VClusterClusterInformer + VClusters() VClusterClusterInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new ClusterInterface. +func New(f internalinterfaces.SharedInformerFactory, tweakListOptions internalinterfaces.TweakListOptionsFunc) ClusterInterface { + return &version{factory: f, tweakListOptions: tweakListOptions} +} + +// KubeClusters returns a KubeClusterClusterInformer +func (v *version) KubeClusters() KubeClusterClusterInformer { + return &kubeClusterClusterInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + +// VClusters returns a VClusterClusterInformer +func (v *version) VClusters() VClusterClusterInformer { + return &vClusterClusterInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + +type Interface interface { + // KubeClusters returns a KubeClusterInformer + KubeClusters() KubeClusterInformer + // VClusters returns a VClusterInformer + VClusters() VClusterInformer +} + +type scopedVersion struct { + factory internalinterfaces.SharedScopedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// New returns a new ClusterInterface. +func NewScoped(f internalinterfaces.SharedScopedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &scopedVersion{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// KubeClusters returns a KubeClusterInformer +func (v *scopedVersion) KubeClusters() KubeClusterInformer { + return &kubeClusterScopedInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + +// VClusters returns a VClusterInformer +func (v *scopedVersion) VClusters() VClusterInformer { + return &vClusterScopedInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} diff --git a/contrib/mounts-virtualworkspace/client/informers/externalversions/mounts/v1alpha1/kubecluster.go b/contrib/mounts-virtualworkspace/client/informers/externalversions/mounts/v1alpha1/kubecluster.go new file mode 100644 index 00000000000..02323808bf6 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/informers/externalversions/mounts/v1alpha1/kubecluster.go @@ -0,0 +1,179 @@ +//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" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + scopedclientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned" + clientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions/internalinterfaces" + mountsv1alpha1listers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/listers/mounts/v1alpha1" +) + +// KubeClusterClusterInformer provides access to a shared informer and lister for +// KubeClusters. +type KubeClusterClusterInformer interface { + Cluster(logicalcluster.Name) KubeClusterInformer + Informer() kcpcache.ScopeableSharedIndexInformer + Lister() mountsv1alpha1listers.KubeClusterClusterLister +} + +type kubeClusterClusterInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewKubeClusterClusterInformer constructs a new informer for KubeCluster 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 NewKubeClusterClusterInformer(client clientset.ClusterInterface, resyncPeriod time.Duration, indexers cache.Indexers) kcpcache.ScopeableSharedIndexInformer { + return NewFilteredKubeClusterClusterInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredKubeClusterClusterInformer constructs a new informer for KubeCluster 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 NewFilteredKubeClusterClusterInformer(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.MountsV1alpha1().KubeClusters().List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.MountsV1alpha1().KubeClusters().Watch(context.TODO(), options) + }, + }, + &mountsv1alpha1.KubeCluster{}, + resyncPeriod, + indexers, + ) +} + +func (f *kubeClusterClusterInformer) defaultInformer(client clientset.ClusterInterface, resyncPeriod time.Duration) kcpcache.ScopeableSharedIndexInformer { + return NewFilteredKubeClusterClusterInformer(client, resyncPeriod, cache.Indexers{ + kcpcache.ClusterIndexName: kcpcache.ClusterIndexFunc, + }, + f.tweakListOptions, + ) +} + +func (f *kubeClusterClusterInformer) Informer() kcpcache.ScopeableSharedIndexInformer { + return f.factory.InformerFor(&mountsv1alpha1.KubeCluster{}, f.defaultInformer) +} + +func (f *kubeClusterClusterInformer) Lister() mountsv1alpha1listers.KubeClusterClusterLister { + return mountsv1alpha1listers.NewKubeClusterClusterLister(f.Informer().GetIndexer()) +} + +// KubeClusterInformer provides access to a shared informer and lister for +// KubeClusters. +type KubeClusterInformer interface { + Informer() cache.SharedIndexInformer + Lister() mountsv1alpha1listers.KubeClusterLister +} + +func (f *kubeClusterClusterInformer) Cluster(clusterName logicalcluster.Name) KubeClusterInformer { + return &kubeClusterInformer{ + informer: f.Informer().Cluster(clusterName), + lister: f.Lister().Cluster(clusterName), + } +} + +type kubeClusterInformer struct { + informer cache.SharedIndexInformer + lister mountsv1alpha1listers.KubeClusterLister +} + +func (f *kubeClusterInformer) Informer() cache.SharedIndexInformer { + return f.informer +} + +func (f *kubeClusterInformer) Lister() mountsv1alpha1listers.KubeClusterLister { + return f.lister +} + +type kubeClusterScopedInformer struct { + factory internalinterfaces.SharedScopedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +func (f *kubeClusterScopedInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&mountsv1alpha1.KubeCluster{}, f.defaultInformer) +} + +func (f *kubeClusterScopedInformer) Lister() mountsv1alpha1listers.KubeClusterLister { + return mountsv1alpha1listers.NewKubeClusterLister(f.Informer().GetIndexer()) +} + +// NewKubeClusterInformer constructs a new informer for KubeCluster 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 NewKubeClusterInformer(client scopedclientset.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredKubeClusterInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredKubeClusterInformer constructs a new informer for KubeCluster 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 NewFilteredKubeClusterInformer(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.MountsV1alpha1().KubeClusters().List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.MountsV1alpha1().KubeClusters().Watch(context.TODO(), options) + }, + }, + &mountsv1alpha1.KubeCluster{}, + resyncPeriod, + indexers, + ) +} + +func (f *kubeClusterScopedInformer) defaultInformer(client scopedclientset.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredKubeClusterInformer(client, resyncPeriod, cache.Indexers{}, f.tweakListOptions) +} diff --git a/contrib/mounts-virtualworkspace/client/informers/externalversions/mounts/v1alpha1/vcluster.go b/contrib/mounts-virtualworkspace/client/informers/externalversions/mounts/v1alpha1/vcluster.go new file mode 100644 index 00000000000..8a3413342b6 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/informers/externalversions/mounts/v1alpha1/vcluster.go @@ -0,0 +1,179 @@ +//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" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + scopedclientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned" + clientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions/internalinterfaces" + mountsv1alpha1listers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/listers/mounts/v1alpha1" +) + +// VClusterClusterInformer provides access to a shared informer and lister for +// VClusters. +type VClusterClusterInformer interface { + Cluster(logicalcluster.Name) VClusterInformer + Informer() kcpcache.ScopeableSharedIndexInformer + Lister() mountsv1alpha1listers.VClusterClusterLister +} + +type vClusterClusterInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewVClusterClusterInformer constructs a new informer for VCluster 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 NewVClusterClusterInformer(client clientset.ClusterInterface, resyncPeriod time.Duration, indexers cache.Indexers) kcpcache.ScopeableSharedIndexInformer { + return NewFilteredVClusterClusterInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredVClusterClusterInformer constructs a new informer for VCluster 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 NewFilteredVClusterClusterInformer(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.MountsV1alpha1().VClusters().List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.MountsV1alpha1().VClusters().Watch(context.TODO(), options) + }, + }, + &mountsv1alpha1.VCluster{}, + resyncPeriod, + indexers, + ) +} + +func (f *vClusterClusterInformer) defaultInformer(client clientset.ClusterInterface, resyncPeriod time.Duration) kcpcache.ScopeableSharedIndexInformer { + return NewFilteredVClusterClusterInformer(client, resyncPeriod, cache.Indexers{ + kcpcache.ClusterIndexName: kcpcache.ClusterIndexFunc, + }, + f.tweakListOptions, + ) +} + +func (f *vClusterClusterInformer) Informer() kcpcache.ScopeableSharedIndexInformer { + return f.factory.InformerFor(&mountsv1alpha1.VCluster{}, f.defaultInformer) +} + +func (f *vClusterClusterInformer) Lister() mountsv1alpha1listers.VClusterClusterLister { + return mountsv1alpha1listers.NewVClusterClusterLister(f.Informer().GetIndexer()) +} + +// VClusterInformer provides access to a shared informer and lister for +// VClusters. +type VClusterInformer interface { + Informer() cache.SharedIndexInformer + Lister() mountsv1alpha1listers.VClusterLister +} + +func (f *vClusterClusterInformer) Cluster(clusterName logicalcluster.Name) VClusterInformer { + return &vClusterInformer{ + informer: f.Informer().Cluster(clusterName), + lister: f.Lister().Cluster(clusterName), + } +} + +type vClusterInformer struct { + informer cache.SharedIndexInformer + lister mountsv1alpha1listers.VClusterLister +} + +func (f *vClusterInformer) Informer() cache.SharedIndexInformer { + return f.informer +} + +func (f *vClusterInformer) Lister() mountsv1alpha1listers.VClusterLister { + return f.lister +} + +type vClusterScopedInformer struct { + factory internalinterfaces.SharedScopedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +func (f *vClusterScopedInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&mountsv1alpha1.VCluster{}, f.defaultInformer) +} + +func (f *vClusterScopedInformer) Lister() mountsv1alpha1listers.VClusterLister { + return mountsv1alpha1listers.NewVClusterLister(f.Informer().GetIndexer()) +} + +// NewVClusterInformer constructs a new informer for VCluster 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 NewVClusterInformer(client scopedclientset.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredVClusterInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredVClusterInformer constructs a new informer for VCluster 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 NewFilteredVClusterInformer(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.MountsV1alpha1().VClusters().List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.MountsV1alpha1().VClusters().Watch(context.TODO(), options) + }, + }, + &mountsv1alpha1.VCluster{}, + resyncPeriod, + indexers, + ) +} + +func (f *vClusterScopedInformer) defaultInformer(client scopedclientset.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredVClusterInformer(client, resyncPeriod, cache.Indexers{}, f.tweakListOptions) +} diff --git a/contrib/mounts-virtualworkspace/client/informers/externalversions/targets/interface.go b/contrib/mounts-virtualworkspace/client/informers/externalversions/targets/interface.go new file mode 100644 index 00000000000..f2cb359dc98 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/informers/externalversions/targets/interface.go @@ -0,0 +1,68 @@ +//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 targets + +import ( + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions/internalinterfaces" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions/targets/v1alpha1" +) + +type ClusterInterface interface { + // V1alpha1 provides access to the shared informers in V1alpha1. + V1alpha1() v1alpha1.ClusterInterface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new ClusterInterface. +func New(f internalinterfaces.SharedInformerFactory, tweakListOptions internalinterfaces.TweakListOptionsFunc) ClusterInterface { + return &group{factory: f, tweakListOptions: tweakListOptions} +} + +// V1alpha1 returns a new v1alpha1.ClusterInterface. +func (g *group) V1alpha1() v1alpha1.ClusterInterface { + return v1alpha1.New(g.factory, g.tweakListOptions) +} + +type Interface interface { + // V1alpha1 provides access to the shared informers in V1alpha1. + V1alpha1() v1alpha1.Interface +} + +type scopedGroup struct { + factory internalinterfaces.SharedScopedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// New returns a new Interface. +func NewScoped(f internalinterfaces.SharedScopedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &scopedGroup{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// V1alpha1 returns a new v1alpha1.ClusterInterface. +func (g *scopedGroup) V1alpha1() v1alpha1.Interface { + return v1alpha1.NewScoped(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/contrib/mounts-virtualworkspace/client/informers/externalversions/targets/v1alpha1/interface.go b/contrib/mounts-virtualworkspace/client/informers/externalversions/targets/v1alpha1/interface.go new file mode 100644 index 00000000000..04c99f88f34 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/informers/externalversions/targets/v1alpha1/interface.go @@ -0,0 +1,81 @@ +//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 ( + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions/internalinterfaces" +) + +type ClusterInterface interface { + // TargetKubeClusters returns a TargetKubeClusterClusterInformer + TargetKubeClusters() TargetKubeClusterClusterInformer + // TargetVClusters returns a TargetVClusterClusterInformer + TargetVClusters() TargetVClusterClusterInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new ClusterInterface. +func New(f internalinterfaces.SharedInformerFactory, tweakListOptions internalinterfaces.TweakListOptionsFunc) ClusterInterface { + return &version{factory: f, tweakListOptions: tweakListOptions} +} + +// TargetKubeClusters returns a TargetKubeClusterClusterInformer +func (v *version) TargetKubeClusters() TargetKubeClusterClusterInformer { + return &targetKubeClusterClusterInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + +// TargetVClusters returns a TargetVClusterClusterInformer +func (v *version) TargetVClusters() TargetVClusterClusterInformer { + return &targetVClusterClusterInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + +type Interface interface { + // TargetKubeClusters returns a TargetKubeClusterInformer + TargetKubeClusters() TargetKubeClusterInformer + // TargetVClusters returns a TargetVClusterInformer + TargetVClusters() TargetVClusterInformer +} + +type scopedVersion struct { + factory internalinterfaces.SharedScopedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// New returns a new ClusterInterface. +func NewScoped(f internalinterfaces.SharedScopedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &scopedVersion{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// TargetKubeClusters returns a TargetKubeClusterInformer +func (v *scopedVersion) TargetKubeClusters() TargetKubeClusterInformer { + return &targetKubeClusterScopedInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + +// TargetVClusters returns a TargetVClusterInformer +func (v *scopedVersion) TargetVClusters() TargetVClusterInformer { + return &targetVClusterScopedInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} diff --git a/contrib/mounts-virtualworkspace/client/informers/externalversions/targets/v1alpha1/targetkubecluster.go b/contrib/mounts-virtualworkspace/client/informers/externalversions/targets/v1alpha1/targetkubecluster.go new file mode 100644 index 00000000000..425331ef252 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/informers/externalversions/targets/v1alpha1/targetkubecluster.go @@ -0,0 +1,179 @@ +//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" + + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" + scopedclientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned" + clientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions/internalinterfaces" + targetsv1alpha1listers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/listers/targets/v1alpha1" +) + +// TargetKubeClusterClusterInformer provides access to a shared informer and lister for +// TargetKubeClusters. +type TargetKubeClusterClusterInformer interface { + Cluster(logicalcluster.Name) TargetKubeClusterInformer + Informer() kcpcache.ScopeableSharedIndexInformer + Lister() targetsv1alpha1listers.TargetKubeClusterClusterLister +} + +type targetKubeClusterClusterInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewTargetKubeClusterClusterInformer constructs a new informer for TargetKubeCluster 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 NewTargetKubeClusterClusterInformer(client clientset.ClusterInterface, resyncPeriod time.Duration, indexers cache.Indexers) kcpcache.ScopeableSharedIndexInformer { + return NewFilteredTargetKubeClusterClusterInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredTargetKubeClusterClusterInformer constructs a new informer for TargetKubeCluster 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 NewFilteredTargetKubeClusterClusterInformer(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.TargetsV1alpha1().TargetKubeClusters().List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TargetsV1alpha1().TargetKubeClusters().Watch(context.TODO(), options) + }, + }, + &targetsv1alpha1.TargetKubeCluster{}, + resyncPeriod, + indexers, + ) +} + +func (f *targetKubeClusterClusterInformer) defaultInformer(client clientset.ClusterInterface, resyncPeriod time.Duration) kcpcache.ScopeableSharedIndexInformer { + return NewFilteredTargetKubeClusterClusterInformer(client, resyncPeriod, cache.Indexers{ + kcpcache.ClusterIndexName: kcpcache.ClusterIndexFunc, + }, + f.tweakListOptions, + ) +} + +func (f *targetKubeClusterClusterInformer) Informer() kcpcache.ScopeableSharedIndexInformer { + return f.factory.InformerFor(&targetsv1alpha1.TargetKubeCluster{}, f.defaultInformer) +} + +func (f *targetKubeClusterClusterInformer) Lister() targetsv1alpha1listers.TargetKubeClusterClusterLister { + return targetsv1alpha1listers.NewTargetKubeClusterClusterLister(f.Informer().GetIndexer()) +} + +// TargetKubeClusterInformer provides access to a shared informer and lister for +// TargetKubeClusters. +type TargetKubeClusterInformer interface { + Informer() cache.SharedIndexInformer + Lister() targetsv1alpha1listers.TargetKubeClusterLister +} + +func (f *targetKubeClusterClusterInformer) Cluster(clusterName logicalcluster.Name) TargetKubeClusterInformer { + return &targetKubeClusterInformer{ + informer: f.Informer().Cluster(clusterName), + lister: f.Lister().Cluster(clusterName), + } +} + +type targetKubeClusterInformer struct { + informer cache.SharedIndexInformer + lister targetsv1alpha1listers.TargetKubeClusterLister +} + +func (f *targetKubeClusterInformer) Informer() cache.SharedIndexInformer { + return f.informer +} + +func (f *targetKubeClusterInformer) Lister() targetsv1alpha1listers.TargetKubeClusterLister { + return f.lister +} + +type targetKubeClusterScopedInformer struct { + factory internalinterfaces.SharedScopedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +func (f *targetKubeClusterScopedInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&targetsv1alpha1.TargetKubeCluster{}, f.defaultInformer) +} + +func (f *targetKubeClusterScopedInformer) Lister() targetsv1alpha1listers.TargetKubeClusterLister { + return targetsv1alpha1listers.NewTargetKubeClusterLister(f.Informer().GetIndexer()) +} + +// NewTargetKubeClusterInformer constructs a new informer for TargetKubeCluster 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 NewTargetKubeClusterInformer(client scopedclientset.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredTargetKubeClusterInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredTargetKubeClusterInformer constructs a new informer for TargetKubeCluster 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 NewFilteredTargetKubeClusterInformer(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.TargetsV1alpha1().TargetKubeClusters().List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TargetsV1alpha1().TargetKubeClusters().Watch(context.TODO(), options) + }, + }, + &targetsv1alpha1.TargetKubeCluster{}, + resyncPeriod, + indexers, + ) +} + +func (f *targetKubeClusterScopedInformer) defaultInformer(client scopedclientset.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredTargetKubeClusterInformer(client, resyncPeriod, cache.Indexers{}, f.tweakListOptions) +} diff --git a/contrib/mounts-virtualworkspace/client/informers/externalversions/targets/v1alpha1/targetvcluster.go b/contrib/mounts-virtualworkspace/client/informers/externalversions/targets/v1alpha1/targetvcluster.go new file mode 100644 index 00000000000..1424571db21 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/informers/externalversions/targets/v1alpha1/targetvcluster.go @@ -0,0 +1,179 @@ +//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" + + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" + scopedclientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned" + clientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions/internalinterfaces" + targetsv1alpha1listers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/listers/targets/v1alpha1" +) + +// TargetVClusterClusterInformer provides access to a shared informer and lister for +// TargetVClusters. +type TargetVClusterClusterInformer interface { + Cluster(logicalcluster.Name) TargetVClusterInformer + Informer() kcpcache.ScopeableSharedIndexInformer + Lister() targetsv1alpha1listers.TargetVClusterClusterLister +} + +type targetVClusterClusterInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewTargetVClusterClusterInformer constructs a new informer for TargetVCluster 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 NewTargetVClusterClusterInformer(client clientset.ClusterInterface, resyncPeriod time.Duration, indexers cache.Indexers) kcpcache.ScopeableSharedIndexInformer { + return NewFilteredTargetVClusterClusterInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredTargetVClusterClusterInformer constructs a new informer for TargetVCluster 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 NewFilteredTargetVClusterClusterInformer(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.TargetsV1alpha1().TargetVClusters().List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TargetsV1alpha1().TargetVClusters().Watch(context.TODO(), options) + }, + }, + &targetsv1alpha1.TargetVCluster{}, + resyncPeriod, + indexers, + ) +} + +func (f *targetVClusterClusterInformer) defaultInformer(client clientset.ClusterInterface, resyncPeriod time.Duration) kcpcache.ScopeableSharedIndexInformer { + return NewFilteredTargetVClusterClusterInformer(client, resyncPeriod, cache.Indexers{ + kcpcache.ClusterIndexName: kcpcache.ClusterIndexFunc, + }, + f.tweakListOptions, + ) +} + +func (f *targetVClusterClusterInformer) Informer() kcpcache.ScopeableSharedIndexInformer { + return f.factory.InformerFor(&targetsv1alpha1.TargetVCluster{}, f.defaultInformer) +} + +func (f *targetVClusterClusterInformer) Lister() targetsv1alpha1listers.TargetVClusterClusterLister { + return targetsv1alpha1listers.NewTargetVClusterClusterLister(f.Informer().GetIndexer()) +} + +// TargetVClusterInformer provides access to a shared informer and lister for +// TargetVClusters. +type TargetVClusterInformer interface { + Informer() cache.SharedIndexInformer + Lister() targetsv1alpha1listers.TargetVClusterLister +} + +func (f *targetVClusterClusterInformer) Cluster(clusterName logicalcluster.Name) TargetVClusterInformer { + return &targetVClusterInformer{ + informer: f.Informer().Cluster(clusterName), + lister: f.Lister().Cluster(clusterName), + } +} + +type targetVClusterInformer struct { + informer cache.SharedIndexInformer + lister targetsv1alpha1listers.TargetVClusterLister +} + +func (f *targetVClusterInformer) Informer() cache.SharedIndexInformer { + return f.informer +} + +func (f *targetVClusterInformer) Lister() targetsv1alpha1listers.TargetVClusterLister { + return f.lister +} + +type targetVClusterScopedInformer struct { + factory internalinterfaces.SharedScopedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +func (f *targetVClusterScopedInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&targetsv1alpha1.TargetVCluster{}, f.defaultInformer) +} + +func (f *targetVClusterScopedInformer) Lister() targetsv1alpha1listers.TargetVClusterLister { + return targetsv1alpha1listers.NewTargetVClusterLister(f.Informer().GetIndexer()) +} + +// NewTargetVClusterInformer constructs a new informer for TargetVCluster 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 NewTargetVClusterInformer(client scopedclientset.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredTargetVClusterInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredTargetVClusterInformer constructs a new informer for TargetVCluster 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 NewFilteredTargetVClusterInformer(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.TargetsV1alpha1().TargetVClusters().List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TargetsV1alpha1().TargetVClusters().Watch(context.TODO(), options) + }, + }, + &targetsv1alpha1.TargetVCluster{}, + resyncPeriod, + indexers, + ) +} + +func (f *targetVClusterScopedInformer) defaultInformer(client scopedclientset.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredTargetVClusterInformer(client, resyncPeriod, cache.Indexers{}, f.tweakListOptions) +} diff --git a/contrib/mounts-virtualworkspace/client/listers/mounts/v1alpha1/kubecluster.go b/contrib/mounts-virtualworkspace/client/listers/mounts/v1alpha1/kubecluster.go new file mode 100644 index 00000000000..721c0217b86 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/listers/mounts/v1alpha1/kubecluster.go @@ -0,0 +1,143 @@ +//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" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" +) + +// KubeClusterClusterLister can list KubeClusters across all workspaces, or scope down to a KubeClusterLister for one workspace. +// All objects returned here must be treated as read-only. +type KubeClusterClusterLister interface { + // List lists all KubeClusters in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*mountsv1alpha1.KubeCluster, err error) + // Cluster returns a lister that can list and get KubeClusters in one workspace. + Cluster(clusterName logicalcluster.Name) KubeClusterLister + KubeClusterClusterListerExpansion +} + +type kubeClusterClusterLister struct { + indexer cache.Indexer +} + +// NewKubeClusterClusterLister returns a new KubeClusterClusterLister. +// 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 NewKubeClusterClusterLister(indexer cache.Indexer) *kubeClusterClusterLister { + return &kubeClusterClusterLister{indexer: indexer} +} + +// List lists all KubeClusters in the indexer across all workspaces. +func (s *kubeClusterClusterLister) List(selector labels.Selector) (ret []*mountsv1alpha1.KubeCluster, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*mountsv1alpha1.KubeCluster)) + }) + return ret, err +} + +// Cluster scopes the lister to one workspace, allowing users to list and get KubeClusters. +func (s *kubeClusterClusterLister) Cluster(clusterName logicalcluster.Name) KubeClusterLister { + return &kubeClusterLister{indexer: s.indexer, clusterName: clusterName} +} + +// KubeClusterLister can list all KubeClusters, or get one in particular. +// All objects returned here must be treated as read-only. +type KubeClusterLister interface { + // List lists all KubeClusters in the workspace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*mountsv1alpha1.KubeCluster, err error) + // Get retrieves the KubeCluster from the indexer for a given workspace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*mountsv1alpha1.KubeCluster, error) + KubeClusterListerExpansion +} + +// kubeClusterLister can list all KubeClusters inside a workspace. +type kubeClusterLister struct { + indexer cache.Indexer + clusterName logicalcluster.Name +} + +// List lists all KubeClusters in the indexer for a workspace. +func (s *kubeClusterLister) List(selector labels.Selector) (ret []*mountsv1alpha1.KubeCluster, err error) { + err = kcpcache.ListAllByCluster(s.indexer, s.clusterName, selector, func(i interface{}) { + ret = append(ret, i.(*mountsv1alpha1.KubeCluster)) + }) + return ret, err +} + +// Get retrieves the KubeCluster from the indexer for a given workspace and name. +func (s *kubeClusterLister) Get(name string) (*mountsv1alpha1.KubeCluster, 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(mountsv1alpha1.Resource("kubeclusters"), name) + } + return obj.(*mountsv1alpha1.KubeCluster), nil +} + +// NewKubeClusterLister returns a new KubeClusterLister. +// We assume that the indexer: +// - is fed by a workspace-scoped LIST+WATCH +// - uses cache.MetaNamespaceKeyFunc as the key function +func NewKubeClusterLister(indexer cache.Indexer) *kubeClusterScopedLister { + return &kubeClusterScopedLister{indexer: indexer} +} + +// kubeClusterScopedLister can list all KubeClusters inside a workspace. +type kubeClusterScopedLister struct { + indexer cache.Indexer +} + +// List lists all KubeClusters in the indexer for a workspace. +func (s *kubeClusterScopedLister) List(selector labels.Selector) (ret []*mountsv1alpha1.KubeCluster, err error) { + err = cache.ListAll(s.indexer, selector, func(i interface{}) { + ret = append(ret, i.(*mountsv1alpha1.KubeCluster)) + }) + return ret, err +} + +// Get retrieves the KubeCluster from the indexer for a given workspace and name. +func (s *kubeClusterScopedLister) Get(name string) (*mountsv1alpha1.KubeCluster, error) { + key := name + obj, exists, err := s.indexer.GetByKey(key) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(mountsv1alpha1.Resource("kubeclusters"), name) + } + return obj.(*mountsv1alpha1.KubeCluster), nil +} diff --git a/contrib/mounts-virtualworkspace/client/listers/mounts/v1alpha1/kubecluster_expansion.go b/contrib/mounts-virtualworkspace/client/listers/mounts/v1alpha1/kubecluster_expansion.go new file mode 100644 index 00000000000..64c24b36c29 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/listers/mounts/v1alpha1/kubecluster_expansion.go @@ -0,0 +1,28 @@ +//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 + +// KubeClusterClusterListerExpansion allows custom methods to be added to KubeClusterClusterLister. +type KubeClusterClusterListerExpansion interface{} + +// KubeClusterListerExpansion allows custom methods to be added to KubeClusterLister. +type KubeClusterListerExpansion interface{} diff --git a/contrib/mounts-virtualworkspace/client/listers/mounts/v1alpha1/vcluster.go b/contrib/mounts-virtualworkspace/client/listers/mounts/v1alpha1/vcluster.go new file mode 100644 index 00000000000..c54e7936466 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/listers/mounts/v1alpha1/vcluster.go @@ -0,0 +1,143 @@ +//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" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" +) + +// VClusterClusterLister can list VClusters across all workspaces, or scope down to a VClusterLister for one workspace. +// All objects returned here must be treated as read-only. +type VClusterClusterLister interface { + // List lists all VClusters in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*mountsv1alpha1.VCluster, err error) + // Cluster returns a lister that can list and get VClusters in one workspace. + Cluster(clusterName logicalcluster.Name) VClusterLister + VClusterClusterListerExpansion +} + +type vClusterClusterLister struct { + indexer cache.Indexer +} + +// NewVClusterClusterLister returns a new VClusterClusterLister. +// 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 NewVClusterClusterLister(indexer cache.Indexer) *vClusterClusterLister { + return &vClusterClusterLister{indexer: indexer} +} + +// List lists all VClusters in the indexer across all workspaces. +func (s *vClusterClusterLister) List(selector labels.Selector) (ret []*mountsv1alpha1.VCluster, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*mountsv1alpha1.VCluster)) + }) + return ret, err +} + +// Cluster scopes the lister to one workspace, allowing users to list and get VClusters. +func (s *vClusterClusterLister) Cluster(clusterName logicalcluster.Name) VClusterLister { + return &vClusterLister{indexer: s.indexer, clusterName: clusterName} +} + +// VClusterLister can list all VClusters, or get one in particular. +// All objects returned here must be treated as read-only. +type VClusterLister interface { + // List lists all VClusters in the workspace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*mountsv1alpha1.VCluster, err error) + // Get retrieves the VCluster from the indexer for a given workspace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*mountsv1alpha1.VCluster, error) + VClusterListerExpansion +} + +// vClusterLister can list all VClusters inside a workspace. +type vClusterLister struct { + indexer cache.Indexer + clusterName logicalcluster.Name +} + +// List lists all VClusters in the indexer for a workspace. +func (s *vClusterLister) List(selector labels.Selector) (ret []*mountsv1alpha1.VCluster, err error) { + err = kcpcache.ListAllByCluster(s.indexer, s.clusterName, selector, func(i interface{}) { + ret = append(ret, i.(*mountsv1alpha1.VCluster)) + }) + return ret, err +} + +// Get retrieves the VCluster from the indexer for a given workspace and name. +func (s *vClusterLister) Get(name string) (*mountsv1alpha1.VCluster, 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(mountsv1alpha1.Resource("vclusters"), name) + } + return obj.(*mountsv1alpha1.VCluster), nil +} + +// NewVClusterLister returns a new VClusterLister. +// We assume that the indexer: +// - is fed by a workspace-scoped LIST+WATCH +// - uses cache.MetaNamespaceKeyFunc as the key function +func NewVClusterLister(indexer cache.Indexer) *vClusterScopedLister { + return &vClusterScopedLister{indexer: indexer} +} + +// vClusterScopedLister can list all VClusters inside a workspace. +type vClusterScopedLister struct { + indexer cache.Indexer +} + +// List lists all VClusters in the indexer for a workspace. +func (s *vClusterScopedLister) List(selector labels.Selector) (ret []*mountsv1alpha1.VCluster, err error) { + err = cache.ListAll(s.indexer, selector, func(i interface{}) { + ret = append(ret, i.(*mountsv1alpha1.VCluster)) + }) + return ret, err +} + +// Get retrieves the VCluster from the indexer for a given workspace and name. +func (s *vClusterScopedLister) Get(name string) (*mountsv1alpha1.VCluster, error) { + key := name + obj, exists, err := s.indexer.GetByKey(key) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(mountsv1alpha1.Resource("vclusters"), name) + } + return obj.(*mountsv1alpha1.VCluster), nil +} diff --git a/contrib/mounts-virtualworkspace/client/listers/mounts/v1alpha1/vcluster_expansion.go b/contrib/mounts-virtualworkspace/client/listers/mounts/v1alpha1/vcluster_expansion.go new file mode 100644 index 00000000000..cdbd56f6408 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/listers/mounts/v1alpha1/vcluster_expansion.go @@ -0,0 +1,28 @@ +//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 + +// VClusterClusterListerExpansion allows custom methods to be added to VClusterClusterLister. +type VClusterClusterListerExpansion interface{} + +// VClusterListerExpansion allows custom methods to be added to VClusterLister. +type VClusterListerExpansion interface{} diff --git a/contrib/mounts-virtualworkspace/client/listers/targets/v1alpha1/targetkubecluster.go b/contrib/mounts-virtualworkspace/client/listers/targets/v1alpha1/targetkubecluster.go new file mode 100644 index 00000000000..6330f31b8bf --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/listers/targets/v1alpha1/targetkubecluster.go @@ -0,0 +1,143 @@ +//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" + + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" +) + +// TargetKubeClusterClusterLister can list TargetKubeClusters across all workspaces, or scope down to a TargetKubeClusterLister for one workspace. +// All objects returned here must be treated as read-only. +type TargetKubeClusterClusterLister interface { + // List lists all TargetKubeClusters in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*targetsv1alpha1.TargetKubeCluster, err error) + // Cluster returns a lister that can list and get TargetKubeClusters in one workspace. + Cluster(clusterName logicalcluster.Name) TargetKubeClusterLister + TargetKubeClusterClusterListerExpansion +} + +type targetKubeClusterClusterLister struct { + indexer cache.Indexer +} + +// NewTargetKubeClusterClusterLister returns a new TargetKubeClusterClusterLister. +// 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 NewTargetKubeClusterClusterLister(indexer cache.Indexer) *targetKubeClusterClusterLister { + return &targetKubeClusterClusterLister{indexer: indexer} +} + +// List lists all TargetKubeClusters in the indexer across all workspaces. +func (s *targetKubeClusterClusterLister) List(selector labels.Selector) (ret []*targetsv1alpha1.TargetKubeCluster, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*targetsv1alpha1.TargetKubeCluster)) + }) + return ret, err +} + +// Cluster scopes the lister to one workspace, allowing users to list and get TargetKubeClusters. +func (s *targetKubeClusterClusterLister) Cluster(clusterName logicalcluster.Name) TargetKubeClusterLister { + return &targetKubeClusterLister{indexer: s.indexer, clusterName: clusterName} +} + +// TargetKubeClusterLister can list all TargetKubeClusters, or get one in particular. +// All objects returned here must be treated as read-only. +type TargetKubeClusterLister interface { + // List lists all TargetKubeClusters in the workspace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*targetsv1alpha1.TargetKubeCluster, err error) + // Get retrieves the TargetKubeCluster from the indexer for a given workspace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*targetsv1alpha1.TargetKubeCluster, error) + TargetKubeClusterListerExpansion +} + +// targetKubeClusterLister can list all TargetKubeClusters inside a workspace. +type targetKubeClusterLister struct { + indexer cache.Indexer + clusterName logicalcluster.Name +} + +// List lists all TargetKubeClusters in the indexer for a workspace. +func (s *targetKubeClusterLister) List(selector labels.Selector) (ret []*targetsv1alpha1.TargetKubeCluster, err error) { + err = kcpcache.ListAllByCluster(s.indexer, s.clusterName, selector, func(i interface{}) { + ret = append(ret, i.(*targetsv1alpha1.TargetKubeCluster)) + }) + return ret, err +} + +// Get retrieves the TargetKubeCluster from the indexer for a given workspace and name. +func (s *targetKubeClusterLister) Get(name string) (*targetsv1alpha1.TargetKubeCluster, 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(targetsv1alpha1.Resource("targetkubeclusters"), name) + } + return obj.(*targetsv1alpha1.TargetKubeCluster), nil +} + +// NewTargetKubeClusterLister returns a new TargetKubeClusterLister. +// We assume that the indexer: +// - is fed by a workspace-scoped LIST+WATCH +// - uses cache.MetaNamespaceKeyFunc as the key function +func NewTargetKubeClusterLister(indexer cache.Indexer) *targetKubeClusterScopedLister { + return &targetKubeClusterScopedLister{indexer: indexer} +} + +// targetKubeClusterScopedLister can list all TargetKubeClusters inside a workspace. +type targetKubeClusterScopedLister struct { + indexer cache.Indexer +} + +// List lists all TargetKubeClusters in the indexer for a workspace. +func (s *targetKubeClusterScopedLister) List(selector labels.Selector) (ret []*targetsv1alpha1.TargetKubeCluster, err error) { + err = cache.ListAll(s.indexer, selector, func(i interface{}) { + ret = append(ret, i.(*targetsv1alpha1.TargetKubeCluster)) + }) + return ret, err +} + +// Get retrieves the TargetKubeCluster from the indexer for a given workspace and name. +func (s *targetKubeClusterScopedLister) Get(name string) (*targetsv1alpha1.TargetKubeCluster, error) { + key := name + obj, exists, err := s.indexer.GetByKey(key) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(targetsv1alpha1.Resource("targetkubeclusters"), name) + } + return obj.(*targetsv1alpha1.TargetKubeCluster), nil +} diff --git a/contrib/mounts-virtualworkspace/client/listers/targets/v1alpha1/targetkubecluster_expansion.go b/contrib/mounts-virtualworkspace/client/listers/targets/v1alpha1/targetkubecluster_expansion.go new file mode 100644 index 00000000000..f68e13c6eac --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/listers/targets/v1alpha1/targetkubecluster_expansion.go @@ -0,0 +1,28 @@ +//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 + +// TargetKubeClusterClusterListerExpansion allows custom methods to be added to TargetKubeClusterClusterLister. +type TargetKubeClusterClusterListerExpansion interface{} + +// TargetKubeClusterListerExpansion allows custom methods to be added to TargetKubeClusterLister. +type TargetKubeClusterListerExpansion interface{} diff --git a/contrib/mounts-virtualworkspace/client/listers/targets/v1alpha1/targetvcluster.go b/contrib/mounts-virtualworkspace/client/listers/targets/v1alpha1/targetvcluster.go new file mode 100644 index 00000000000..63d722f3d93 --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/listers/targets/v1alpha1/targetvcluster.go @@ -0,0 +1,143 @@ +//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" + + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" +) + +// TargetVClusterClusterLister can list TargetVClusters across all workspaces, or scope down to a TargetVClusterLister for one workspace. +// All objects returned here must be treated as read-only. +type TargetVClusterClusterLister interface { + // List lists all TargetVClusters in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*targetsv1alpha1.TargetVCluster, err error) + // Cluster returns a lister that can list and get TargetVClusters in one workspace. + Cluster(clusterName logicalcluster.Name) TargetVClusterLister + TargetVClusterClusterListerExpansion +} + +type targetVClusterClusterLister struct { + indexer cache.Indexer +} + +// NewTargetVClusterClusterLister returns a new TargetVClusterClusterLister. +// 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 NewTargetVClusterClusterLister(indexer cache.Indexer) *targetVClusterClusterLister { + return &targetVClusterClusterLister{indexer: indexer} +} + +// List lists all TargetVClusters in the indexer across all workspaces. +func (s *targetVClusterClusterLister) List(selector labels.Selector) (ret []*targetsv1alpha1.TargetVCluster, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*targetsv1alpha1.TargetVCluster)) + }) + return ret, err +} + +// Cluster scopes the lister to one workspace, allowing users to list and get TargetVClusters. +func (s *targetVClusterClusterLister) Cluster(clusterName logicalcluster.Name) TargetVClusterLister { + return &targetVClusterLister{indexer: s.indexer, clusterName: clusterName} +} + +// TargetVClusterLister can list all TargetVClusters, or get one in particular. +// All objects returned here must be treated as read-only. +type TargetVClusterLister interface { + // List lists all TargetVClusters in the workspace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*targetsv1alpha1.TargetVCluster, err error) + // Get retrieves the TargetVCluster from the indexer for a given workspace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*targetsv1alpha1.TargetVCluster, error) + TargetVClusterListerExpansion +} + +// targetVClusterLister can list all TargetVClusters inside a workspace. +type targetVClusterLister struct { + indexer cache.Indexer + clusterName logicalcluster.Name +} + +// List lists all TargetVClusters in the indexer for a workspace. +func (s *targetVClusterLister) List(selector labels.Selector) (ret []*targetsv1alpha1.TargetVCluster, err error) { + err = kcpcache.ListAllByCluster(s.indexer, s.clusterName, selector, func(i interface{}) { + ret = append(ret, i.(*targetsv1alpha1.TargetVCluster)) + }) + return ret, err +} + +// Get retrieves the TargetVCluster from the indexer for a given workspace and name. +func (s *targetVClusterLister) Get(name string) (*targetsv1alpha1.TargetVCluster, 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(targetsv1alpha1.Resource("targetvclusters"), name) + } + return obj.(*targetsv1alpha1.TargetVCluster), nil +} + +// NewTargetVClusterLister returns a new TargetVClusterLister. +// We assume that the indexer: +// - is fed by a workspace-scoped LIST+WATCH +// - uses cache.MetaNamespaceKeyFunc as the key function +func NewTargetVClusterLister(indexer cache.Indexer) *targetVClusterScopedLister { + return &targetVClusterScopedLister{indexer: indexer} +} + +// targetVClusterScopedLister can list all TargetVClusters inside a workspace. +type targetVClusterScopedLister struct { + indexer cache.Indexer +} + +// List lists all TargetVClusters in the indexer for a workspace. +func (s *targetVClusterScopedLister) List(selector labels.Selector) (ret []*targetsv1alpha1.TargetVCluster, err error) { + err = cache.ListAll(s.indexer, selector, func(i interface{}) { + ret = append(ret, i.(*targetsv1alpha1.TargetVCluster)) + }) + return ret, err +} + +// Get retrieves the TargetVCluster from the indexer for a given workspace and name. +func (s *targetVClusterScopedLister) Get(name string) (*targetsv1alpha1.TargetVCluster, error) { + key := name + obj, exists, err := s.indexer.GetByKey(key) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(targetsv1alpha1.Resource("targetvclusters"), name) + } + return obj.(*targetsv1alpha1.TargetVCluster), nil +} diff --git a/contrib/mounts-virtualworkspace/client/listers/targets/v1alpha1/targetvcluster_expansion.go b/contrib/mounts-virtualworkspace/client/listers/targets/v1alpha1/targetvcluster_expansion.go new file mode 100644 index 00000000000..37745d27f0d --- /dev/null +++ b/contrib/mounts-virtualworkspace/client/listers/targets/v1alpha1/targetvcluster_expansion.go @@ -0,0 +1,28 @@ +//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 + +// TargetVClusterClusterListerExpansion allows custom methods to be added to TargetVClusterClusterLister. +type TargetVClusterClusterListerExpansion interface{} + +// TargetVClusterListerExpansion allows custom methods to be added to TargetVClusterLister. +type TargetVClusterListerExpansion interface{} diff --git a/contrib/mounts-virtualworkspace/cmd/virtual-workspaces/command/cmd.go b/contrib/mounts-virtualworkspace/cmd/virtual-workspaces/command/cmd.go new file mode 100644 index 00000000000..350323e94e5 --- /dev/null +++ b/contrib/mounts-virtualworkspace/cmd/virtual-workspaces/command/cmd.go @@ -0,0 +1,262 @@ +/* +Copyright 2023 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 command + +import ( + "context" + "fmt" + "io" + "net/http" + "net/url" + "time" + + kcpkubernetesclient "github.com/kcp-dev/client-go/kubernetes" + kcpfeatures "github.com/kcp-dev/kcp/pkg/features" + "github.com/kcp-dev/kcp/pkg/server/bootstrap" + virtualrootapiserver "github.com/kcp-dev/kcp/pkg/virtual/framework/rootapiserver" + virtualoptions "github.com/kcp-dev/kcp/pkg/virtual/options" + "github.com/spf13/cobra" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apimachinery/pkg/util/wait" + genericapiserver "k8s.io/apiserver/pkg/server" + "k8s.io/apiserver/pkg/server/filters" + "k8s.io/client-go/pkg/version" + "k8s.io/client-go/tools/clientcmd" + logsapiv1 "k8s.io/component-base/logs/api/v1" + "k8s.io/klog/v2" + + mountsclientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster" + mountsinformers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/cmd/virtual-workspaces/options" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/reconciler" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" +) + +func NewCommand(ctx context.Context, errout io.Writer) *cobra.Command { + opts := options.NewOptions() + + // Default to -v=2 + opts.Logs.Verbosity = logsapiv1.VerbosityLevel(2) + + cmd := &cobra.Command{ + Use: "workspaces", + Short: "Launch virtual cluster-proxy workspace apiservers", + Long: "Start the root virtual workspace apiserver to enable virtual workspace management.", + + RunE: func(c *cobra.Command, args []string) error { + if err := logsapiv1.ValidateAndApply(opts.Logs, kcpfeatures.DefaultFeatureGate); err != nil { + return err + } + if err := opts.Validate(); err != nil { + return err + } + return nil + }, + } + + startCmd := &cobra.Command{ + Use: "start", + Short: "Start the virtual workspaces server", + PersistentPreRunE: func(*cobra.Command, []string) error { + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + if err := opts.Validate(); err != nil { + return err + } + + return Start(ctx, opts) + }, + } + + opts.AddFlags(cmd.Flags()) + opts.AddFlags(startCmd.Flags()) + + cmd.AddCommand(startCmd) + + return cmd +} + +// Start takes the options, starts the API server and waits until stopCh is closed or initial listening fails. +func Start(ctx context.Context, o *options.Options) error { + logger := klog.FromContext(ctx).WithValues("component", "virtual-workspaces") + // parse kubeconfig + logger.Info("Starting virtual workspace apiserver") + kubeConfig, err := readKubeConfig(o.KubeconfigFile, o.Context) + if err != nil { + return err + } + + nonIdentityConfig, err := kubeConfig.ClientConfig() + if err != nil { + return err + } + + // parse cache kubeconfig + // TODO: add cache kubeconfig flag + defaultCacheClientConfig, err := kubeConfig.ClientConfig() + if err != nil { + return err + } + cacheConfig, err := o.Cache.RestConfig(defaultCacheClientConfig) + if err != nil { + return err + } + + // Don't throttle + nonIdentityConfig.QPS = -1 + + u, err := url.Parse(nonIdentityConfig.Host) + if err != nil { + return err + } + u.Path = "" + nonIdentityConfig.Host = u.String() + + localShardKubeClusterClient, err := kcpkubernetesclient.NewForConfig(nonIdentityConfig) + if err != nil { + return err + } + + // resolve identities for system APIBindings + logger.Info("Resolving identities") + identityConfig, resolveIdentities := bootstrap.NewConfigWithWildcardIdentities(nonIdentityConfig, bootstrap.KcpRootGroupExportNames, bootstrap.KcpRootGroupResourceExportNames, localShardKubeClusterClient) + if err := wait.PollUntilContextCancel(ctx, time.Millisecond*500, true, func(ctx context.Context) (bool, error) { + if err := resolveIdentities(ctx); err != nil { + fmt.Println(err) + logger.V(4).Info("failed to resolve identities, keeping trying: ", "err", err) + return false, nil + } + return true, nil + }); err != nil { + return fmt.Errorf("failed to get or create identities: %w", err) + } + logger.Info("Resolving identities done") + + cacheProxyClusterClient, err := mountsclientset.NewForConfig(cacheConfig) + if err != nil { + return err + } + mountsInformers := mountsinformers.NewSharedInformerFactory(cacheProxyClusterClient, 10*time.Minute) + + if o.ProfilerAddress != "" { + //nolint:errcheck,gosec + go http.ListenAndServe(o.ProfilerAddress, nil) + } + + // create apiserver + scheme := runtime.NewScheme() + metav1.AddToGroupVersion(scheme, schema.GroupVersion{Group: "", Version: "v1"}) + codecs := serializer.NewCodecFactory(scheme) + recommendedConfig := genericapiserver.NewRecommendedConfig(codecs) + if err := o.SecureServing.ApplyTo(&recommendedConfig.Config.SecureServing); err != nil { + return err + } + if err := o.Authentication.ApplyTo(&recommendedConfig.Authentication, recommendedConfig.SecureServing, recommendedConfig.OpenAPIConfig); err != nil { + return err + } + if err := o.Audit.ApplyTo(&recommendedConfig.Config); err != nil { + return err + } + + rootAPIServerConfig, err := virtualrootapiserver.NewConfig(recommendedConfig) + if err != nil { + return err + } + + authorizationOptions := virtualoptions.NewAuthorization() + authorizationOptions.AlwaysAllowGroups = o.Authorization.AlwaysAllowGroups + authorizationOptions.AlwaysAllowPaths = o.Authorization.AlwaysAllowPaths + if err := authorizationOptions.ApplyTo(&recommendedConfig.Config, func() []virtualrootapiserver.NamedVirtualWorkspace { + return rootAPIServerConfig.Extra.VirtualWorkspaces + }); err != nil { + return err + } + + if err := o.Authorization.ApplyTo(&recommendedConfig.Config, func() []virtualrootapiserver.NamedVirtualWorkspace { + return rootAPIServerConfig.Extra.VirtualWorkspaces + }); err != nil { + return err + } + + // state store is used to share clients between controller and virtual workspace apiserver. + store := state.NewClientSetStore() + + logger.Info("Configuring virtual workspace apiserver") + rootAPIServerConfig.Extra.VirtualWorkspaces, err = o.ProxyVirtualWorkspaces.NewVirtualWorkspaces(o.RootPathPrefix, identityConfig, mountsInformers, store) + if err != nil { + return err + } + + rootAPIServerConfig.Generic.LongRunningFunc = filters.BasicLongRunningRequestCheck( + sets.NewString("watch", "proxy"), + sets.NewString("attach", "exec", "proxy", "log", "portforward"), + ) + + completedRootAPIServerConfig := rootAPIServerConfig.Complete() + rootAPIServer, err := virtualrootapiserver.NewServer(completedRootAPIServerConfig, genericapiserver.NewEmptyDelegate()) + if err != nil { + return err + } + + preparedRootAPIServer := rootAPIServer.GenericAPIServer.PrepareRun() + + // this **must** be done after PrepareRun() as it sets up the openapi endpoints + if err := completedRootAPIServerConfig.WithOpenAPIAggregationController(preparedRootAPIServer.GenericAPIServer); err != nil { + return err + } + + logger.Info("Starting informers") + mountsInformers.Start(ctx.Done()) + + mountsInformers.WaitForCacheSync(ctx.Done()) + + // start controllers. + // TODO: Move to separate binary + manager, err := reconciler.NewManager(ctx, o.ProxyVirtualWorkspaces.Proxy.VirtualWorkspaceHostname, nonIdentityConfig, store) + if err != nil { + return err + } + if err := manager.Start(ctx); err != nil { + return err + } + + logger.Info("Starting virtual workspace apiserver on ", "externalAddress", rootAPIServerConfig.Generic.ExternalAddress, "version", version.Get().String()) + return preparedRootAPIServer.Run(ctx.Done()) +} + +func readKubeConfig(kubeConfigFile, context string) (clientcmd.ClientConfig, error) { + loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() + loadingRules.ExplicitPath = kubeConfigFile + + startingConfig, err := loadingRules.GetStartingConfig() + if err != nil { + return nil, err + } + + overrides := &clientcmd.ConfigOverrides{ + CurrentContext: context, + } + + clientConfig := clientcmd.NewDefaultClientConfig(*startingConfig, overrides) + return clientConfig, nil +} diff --git a/contrib/mounts-virtualworkspace/cmd/virtual-workspaces/main.go b/contrib/mounts-virtualworkspace/cmd/virtual-workspaces/main.go new file mode 100644 index 00000000000..c2816104d6d --- /dev/null +++ b/contrib/mounts-virtualworkspace/cmd/virtual-workspaces/main.go @@ -0,0 +1,41 @@ +/* +Copyright 2023 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 main + +import ( + goflag "flag" + "fmt" + "os" + + "github.com/spf13/pflag" + + genericapiserver "k8s.io/apiserver/pkg/server" + + virtualworkspacecommand "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/cmd/virtual-workspaces/command" +) + +func main() { + ctx := genericapiserver.SetupSignalContext() + + pflag.CommandLine.AddGoFlagSet(goflag.CommandLine) + + command := virtualworkspacecommand.NewCommand(ctx, os.Stderr) + if err := command.Execute(); err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + os.Exit(1) + } +} diff --git a/contrib/mounts-virtualworkspace/cmd/virtual-workspaces/options/options.go b/contrib/mounts-virtualworkspace/cmd/virtual-workspaces/options/options.go new file mode 100644 index 00000000000..b78f7eb35d9 --- /dev/null +++ b/contrib/mounts-virtualworkspace/cmd/virtual-workspaces/options/options.go @@ -0,0 +1,121 @@ +/* +Copyright 2023 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" + "io" + "path/filepath" + "strings" + + cacheoptions "github.com/kcp-dev/kcp/pkg/cache/client/options" + virtualoptions "github.com/kcp-dev/kcp/pkg/virtual/options" + "github.com/spf13/cobra" + "github.com/spf13/pflag" + + utilerrors "k8s.io/apimachinery/pkg/util/errors" + genericapiserveroptions "k8s.io/apiserver/pkg/server/options" + "k8s.io/component-base/logs" + logsapiv1 "k8s.io/component-base/logs/api/v1" + + proxyvwoptions "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/virtual/options" +) + +// DefaultRootPathPrefix is basically constant forever, or we risk a breaking change. The +// kubectl plugin for example will use this prefix to generate the root path, and because +// we don't control kubectl plugin updates, we cannot change this prefix. +const DefaultRootPathPrefix string = "/services" + +type Options struct { + Output io.Writer + + KubeconfigFile string + Context string + RootPathPrefix string + + Cache cacheoptions.Cache + SecureServing genericapiserveroptions.SecureServingOptions + Authentication genericapiserveroptions.DelegatingAuthenticationOptions + Authorization virtualoptions.Authorization + Audit genericapiserveroptions.AuditOptions + + Logs *logs.Options + + ProxyVirtualWorkspaces proxyvwoptions.Options + + ProfilerAddress string +} + +func NewOptions() *Options { + opts := &Options{ + Output: nil, + + RootPathPrefix: DefaultRootPathPrefix, + + Cache: *cacheoptions.NewCache(), + SecureServing: *genericapiserveroptions.NewSecureServingOptions(), + Authentication: *genericapiserveroptions.NewDelegatingAuthenticationOptions(), + Authorization: *virtualoptions.NewAuthorization(), + Audit: *genericapiserveroptions.NewAuditOptions(), + Logs: logs.NewOptions(), + + ProxyVirtualWorkspaces: *proxyvwoptions.NewOptions(), + ProfilerAddress: "", + } + + opts.SecureServing.ServerCert.CertKey.CertFile = filepath.Join(".", ".kcp", "apiserver.crt") + opts.SecureServing.ServerCert.CertKey.KeyFile = filepath.Join(".", ".kcp", "apiserver.key") + opts.SecureServing.BindPort = 6444 + opts.Authentication.SkipInClusterLookup = true + + // Default to -v=2 + opts.Logs.Verbosity = logsapiv1.VerbosityLevel(2) + + return opts +} + +func (o *Options) AddFlags(flags *pflag.FlagSet) { + o.Cache.AddFlags(flags) + o.SecureServing.AddFlags(flags) + o.Authentication.AddFlags(flags) + o.Audit.AddFlags(flags) + logsapiv1.AddFlags(o.Logs, flags) + o.ProxyVirtualWorkspaces.AddFlags(flags) + + flags.StringVar(&o.KubeconfigFile, "kubeconfig", o.KubeconfigFile, "The kubeconfig file of the KCP instance that hosts workspaces.") + _ = cobra.MarkFlagRequired(flags, "kubeconfig") + + flags.StringVar(&o.Context, "context", o.Context, "Name of the context in the kubeconfig file to use") + flags.StringVar(&o.ProfilerAddress, "profiler-address", "", "[Address]:port to bind the profiler to") +} + +func (o *Options) Validate() error { + errs := []error{} + errs = append(errs, o.Cache.Validate()...) + errs = append(errs, o.SecureServing.Validate()...) + errs = append(errs, o.Authentication.Validate()...) + errs = append(errs, o.ProxyVirtualWorkspaces.Validate()...) + + if len(o.KubeconfigFile) == 0 { + errs = append(errs, fmt.Errorf("--kubeconfig is required for this command")) + } + if !strings.HasPrefix(o.RootPathPrefix, "/") { + errs = append(errs, fmt.Errorf("RootPathPrefix %q must start with /", o.RootPathPrefix)) + } + + return utilerrors.NewAggregate(errs) +} diff --git a/contrib/mounts-virtualworkspace/config/crds/mounts.contrib.kcp.io_kubeclusters.yaml b/contrib/mounts-virtualworkspace/config/crds/mounts.contrib.kcp.io_kubeclusters.yaml new file mode 100644 index 00000000000..9333ea98624 --- /dev/null +++ b/contrib/mounts-virtualworkspace/config/crds/mounts.contrib.kcp.io_kubeclusters.yaml @@ -0,0 +1,187 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: kubeclusters.mounts.contrib.kcp.io +spec: + group: mounts.contrib.kcp.io + names: + categories: + - contrib + kind: KubeCluster + listKind: KubeClusterList + plural: kubeclusters + singular: kubecluster + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="ClusterReady")].status + name: Ready + type: string + - jsonPath: .status.phase + name: Phase + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: KubeCluster describes the current KubeCluster proxy object. + properties: + apiVersion: + 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 + kind: + 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 + metadata: + type: object + spec: + description: KubeClusterSpec is the specification of the Kube cluster + proxy resource. + properties: + mode: + default: Direct + description: Mode is the mode of the KubeCluster proxy(Direct, Delegated). + enum: + - Direct + - Delegated + type: string + secretRef: + description: |- + SecretRef is a reference to the secret containing the kubeconfig for the target cluster. + Used only in Direct mode. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + secretString: + description: |- + SecretString is used to identify Target cluster in the backend for mount. + Used only in Delegated mode. + type: string + type: object + status: + description: KubeClusterStatus communicates the observed state of the + Kube cluster proxy. + properties: + URL: + description: |- + url is the address under which the Kubernetes-cluster-like endpoint + can be found. This URL can be used to access the cluster with standard Kubernetes + client libraries and command line tools via proxy. + type: string + conditions: + description: Current processing state of the Cluster proxy. + items: + description: Condition defines an observation of a object operational + state. + properties: + lastTransitionTime: + description: |- + Last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when + the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + A human readable message indicating details about the transition. + This field may be empty. + type: string + reason: + description: |- + The reason for the condition's last transition in CamelCase. + The specific API may choose whether or not this field is considered a guaranteed API. + This field may not be empty. + type: string + severity: + description: |- + Severity provides an explicit classification of Reason code, so the users or machines can immediately + understand the current situation and act accordingly. + The Severity field MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: |- + Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability to deconflict is important. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + lastProxyHeartbeatTime: + description: A timestamp indicating when the proxy last reported status. + format: date-time + type: string + phase: + default: Initializing + description: Phase of the cluster proxy (Initializing, Ready). + enum: + - Initializing + - Connecting + - Ready + - Unknown + type: string + secretString: + description: SecretString is mountpoint secret string for clients + to mount. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/contrib/mounts-virtualworkspace/config/crds/mounts.contrib.kcp.io_vclusters.yaml b/contrib/mounts-virtualworkspace/config/crds/mounts.contrib.kcp.io_vclusters.yaml new file mode 100644 index 00000000000..da0dc6df2f0 --- /dev/null +++ b/contrib/mounts-virtualworkspace/config/crds/mounts.contrib.kcp.io_vclusters.yaml @@ -0,0 +1,191 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: vclusters.mounts.contrib.kcp.io +spec: + group: mounts.contrib.kcp.io + names: + categories: + - contrib + kind: VCluster + listKind: VClusterList + plural: vclusters + singular: vcluster + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="ClusterReady")].status + name: Ready + type: string + - jsonPath: .status.phase + name: Phase + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: VCluster describes the current VCluster proxy object. + properties: + apiVersion: + 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 + kind: + 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 + metadata: + type: object + spec: + description: VClusterSpec is the specification of the VCluster cluster + proxy resource. + properties: + mode: + default: Delegated + description: Mode is the mode of the KubeCluster proxy(Direct, Delegated). + enum: + - Delegated + type: string + secretRef: + description: |- + SecretRef is a reference to the secret containing the kubeconfig for the target cluster. + Used only in Direct mode. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + secretString: + description: |- + SecretString is used to identify Target cluster in the backend for mount. + Used only in Delegated mode. + type: string + version: + default: 0.20.2 + description: Version is the version of the VCluster proxy. + type: string + type: object + status: + description: VClusterStatus communicates the observed state of the VCluster + cluster proxy. + properties: + URL: + description: |- + url is the address under which the Kubernetes-cluster-like endpoint + can be found. This URL can be used to access the cluster with standard Kubernetes + client libraries and command line tools via proxy. + type: string + conditions: + description: Current processing state of the Cluster proxy. + items: + description: Condition defines an observation of a object operational + state. + properties: + lastTransitionTime: + description: |- + Last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when + the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + A human readable message indicating details about the transition. + This field may be empty. + type: string + reason: + description: |- + The reason for the condition's last transition in CamelCase. + The specific API may choose whether or not this field is considered a guaranteed API. + This field may not be empty. + type: string + severity: + description: |- + Severity provides an explicit classification of Reason code, so the users or machines can immediately + understand the current situation and act accordingly. + The Severity field MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: |- + Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability to deconflict is important. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + lastProxyHeartbeatTime: + description: A timestamp indicating when the proxy last reported status. + format: date-time + type: string + phase: + default: Initializing + description: Phase of the cluster proxy (Initializing;Connecting;Ready;Unknown). + enum: + - Initializing + - Connecting + - Ready + - Unknown + type: string + secretString: + description: |- + SecretString is the secret string used to identify the target cluster in the backend for mount. + Used in both codes, as it is used to identify the target cluster in vcluster cluster pool. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/contrib/mounts-virtualworkspace/config/crds/targets.contrib.kcp.io_targetkubeclusters.yaml b/contrib/mounts-virtualworkspace/config/crds/targets.contrib.kcp.io_targetkubeclusters.yaml new file mode 100644 index 00000000000..cdedce24099 --- /dev/null +++ b/contrib/mounts-virtualworkspace/config/crds/targets.contrib.kcp.io_targetkubeclusters.yaml @@ -0,0 +1,171 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: targetkubeclusters.targets.contrib.kcp.io +spec: + group: targets.contrib.kcp.io + names: + categories: + - contrib + kind: TargetKubeCluster + listKind: TargetKubeClusterList + plural: targetkubeclusters + singular: targetkubecluster + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="ClusterReady")].status + name: Ready + type: string + - jsonPath: .status.phase + name: Phase + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: KubeCluster describes the current KubeCluster target object. + properties: + apiVersion: + 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 + kind: + 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 + metadata: + type: object + spec: + description: TargetKubeClusterSpec is the specification of the Target + Kube cluster proxy resource. + properties: + secretRef: + description: SecretRef is a reference to the secret containing the + kubeconfig for the target cluster. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + type: object + status: + description: TargetKubeClusterStatus communicates the observed state of + the Kube cluster proxy. + properties: + URL: + description: URL is the address under which mount should be using. + type: string + conditions: + description: Current processing state of the Cluster proxy. + items: + description: Condition defines an observation of a object operational + state. + properties: + lastTransitionTime: + description: |- + Last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when + the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + A human readable message indicating details about the transition. + This field may be empty. + type: string + reason: + description: |- + The reason for the condition's last transition in CamelCase. + The specific API may choose whether or not this field is considered a guaranteed API. + This field may not be empty. + type: string + severity: + description: |- + Severity provides an explicit classification of Reason code, so the users or machines can immediately + understand the current situation and act accordingly. + The Severity field MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: |- + Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability to deconflict is important. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + lastProxyHeartbeatTime: + description: A timestamp indicating when the proxy last reported status. + format: date-time + type: string + phase: + default: Initializing + description: Phase of the cluster proxy (Initializing, Ready). + enum: + - Initializing + - Connecting + - Ready + - Unknown + type: string + secretString: + description: SecretString is mountpoint secret string for clients + to mount. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/contrib/mounts-virtualworkspace/config/crds/targets.contrib.kcp.io_targetvclusters.yaml b/contrib/mounts-virtualworkspace/config/crds/targets.contrib.kcp.io_targetvclusters.yaml new file mode 100644 index 00000000000..527b05bb82c --- /dev/null +++ b/contrib/mounts-virtualworkspace/config/crds/targets.contrib.kcp.io_targetvclusters.yaml @@ -0,0 +1,171 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: targetvclusters.targets.contrib.kcp.io +spec: + group: targets.contrib.kcp.io + names: + categories: + - contrib + kind: TargetVCluster + listKind: TargetVClusterList + plural: targetvclusters + singular: targetvcluster + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="ClusterReady")].status + name: Ready + type: string + - jsonPath: .status.phase + name: Phase + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: TargetVCluster describes the current VCluster target object. + properties: + apiVersion: + 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 + kind: + 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 + metadata: + type: object + spec: + description: TargetVClusterSpec is the specification of the Target Kube + cluster proxy resource. + properties: + secretRef: + description: SecretRef is a reference to the secret containing the + kubeconfig for the target cluster. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + type: object + status: + description: TargetVClusterStatus communicates the observed state of the + Kube cluster proxy. + properties: + URL: + description: URL is the address under which mount should be using. + type: string + conditions: + description: Current processing state of the Cluster proxy. + items: + description: Condition defines an observation of a object operational + state. + properties: + lastTransitionTime: + description: |- + Last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when + the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + A human readable message indicating details about the transition. + This field may be empty. + type: string + reason: + description: |- + The reason for the condition's last transition in CamelCase. + The specific API may choose whether or not this field is considered a guaranteed API. + This field may not be empty. + type: string + severity: + description: |- + Severity provides an explicit classification of Reason code, so the users or machines can immediately + understand the current situation and act accordingly. + The Severity field MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: |- + Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability to deconflict is important. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + lastProxyHeartbeatTime: + description: A timestamp indicating when the proxy last reported status. + format: date-time + type: string + phase: + default: Initializing + description: Phase of the cluster proxy (Initializing, Ready). + enum: + - Initializing + - Connecting + - Ready + - Unknown + type: string + secretString: + description: SecretString is mountpoint secret string for clients + to mount. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/contrib/mounts-virtualworkspace/config/mounts/resources/apibinding-mounts.yaml b/contrib/mounts-virtualworkspace/config/mounts/resources/apibinding-mounts.yaml new file mode 100644 index 00000000000..d1700d96602 --- /dev/null +++ b/contrib/mounts-virtualworkspace/config/mounts/resources/apibinding-mounts.yaml @@ -0,0 +1,9 @@ +apiVersion: apis.kcp.io/v1alpha1 +kind: APIBinding +metadata: + name: mounts.contrib.kcp.io +spec: + reference: + export: + name: mounts.contrib.kcp.io + path: root:providers:mounts diff --git a/contrib/mounts-virtualworkspace/config/mounts/resources/apibinding-targets.yaml b/contrib/mounts-virtualworkspace/config/mounts/resources/apibinding-targets.yaml new file mode 100644 index 00000000000..f9ea1988aec --- /dev/null +++ b/contrib/mounts-virtualworkspace/config/mounts/resources/apibinding-targets.yaml @@ -0,0 +1,13 @@ +apiVersion: apis.kcp.io/v1alpha1 +kind: APIBinding +metadata: + name: targets.contrib.kcp.io +spec: + reference: + export: + name: targets.contrib.kcp.io + path: root:providers:mounts + permissionClaims: + - all: true + resource: secrets + state: Accepted diff --git a/contrib/mounts-virtualworkspace/config/mounts/resources/apiexport-mounts.contrib.kcp.io.yaml b/contrib/mounts-virtualworkspace/config/mounts/resources/apiexport-mounts.contrib.kcp.io.yaml new file mode 100644 index 00000000000..79eeaf4ec2f --- /dev/null +++ b/contrib/mounts-virtualworkspace/config/mounts/resources/apiexport-mounts.contrib.kcp.io.yaml @@ -0,0 +1,10 @@ +apiVersion: apis.kcp.io/v1alpha1 +kind: APIExport +metadata: + creationTimestamp: null + name: mounts.contrib.kcp.io +spec: + latestResourceSchemas: + - v241031-8967b5418.kubeclusters.mounts.contrib.kcp.io + - v241101-d11f156a5.vclusters.mounts.contrib.kcp.io +status: {} diff --git a/contrib/mounts-virtualworkspace/config/mounts/resources/apiexport-targets.contrib.kcp.io.yaml b/contrib/mounts-virtualworkspace/config/mounts/resources/apiexport-targets.contrib.kcp.io.yaml new file mode 100644 index 00000000000..e44e93d3f21 --- /dev/null +++ b/contrib/mounts-virtualworkspace/config/mounts/resources/apiexport-targets.contrib.kcp.io.yaml @@ -0,0 +1,13 @@ +apiVersion: apis.kcp.io/v1alpha1 +kind: APIExport +metadata: + creationTimestamp: null + name: targets.contrib.kcp.io +spec: + latestResourceSchemas: + - v241029-8967b5418.targetkubeclusters.targets.contrib.kcp.io + - v241029-8967b5418.targetvclusters.targets.contrib.kcp.io + permissionClaims: + - all: true + resource: secrets +status: {} diff --git a/contrib/mounts-virtualworkspace/config/mounts/resources/apiresourceschema-kubeclusters.mounts.contrib.kcp.io.yaml b/contrib/mounts-virtualworkspace/config/mounts/resources/apiresourceschema-kubeclusters.mounts.contrib.kcp.io.yaml new file mode 100644 index 00000000000..33cdad7a277 --- /dev/null +++ b/contrib/mounts-virtualworkspace/config/mounts/resources/apiresourceschema-kubeclusters.mounts.contrib.kcp.io.yaml @@ -0,0 +1,184 @@ +apiVersion: apis.kcp.io/v1alpha1 +kind: APIResourceSchema +metadata: + creationTimestamp: null + name: v241031-8967b5418.kubeclusters.mounts.contrib.kcp.io +spec: + group: mounts.contrib.kcp.io + names: + categories: + - contrib + kind: KubeCluster + listKind: KubeClusterList + plural: kubeclusters + singular: kubecluster + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="ClusterReady")].status + name: Ready + type: string + - jsonPath: .status.phase + name: Phase + type: string + name: v1alpha1 + schema: + description: KubeCluster describes the current KubeCluster proxy object. + properties: + apiVersion: + 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 + kind: + 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 + metadata: + type: object + spec: + description: KubeClusterSpec is the specification of the Kube cluster proxy + resource. + properties: + mode: + default: Direct + description: Mode is the mode of the KubeCluster proxy(Direct, Delegated). + enum: + - Direct + - Delegated + type: string + secretRef: + description: |- + SecretRef is a reference to the secret containing the kubeconfig for the target cluster. + Used only in Direct mode. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + secretString: + description: |- + SecretString is used to identify Target cluster in the backend for mount. + Used only in Delegated mode. + type: string + type: object + status: + description: KubeClusterStatus communicates the observed state of the Kube + cluster proxy. + properties: + URL: + description: |- + url is the address under which the Kubernetes-cluster-like endpoint + can be found. This URL can be used to access the cluster with standard Kubernetes + client libraries and command line tools via proxy. + type: string + conditions: + description: Current processing state of the Cluster proxy. + items: + description: Condition defines an observation of a object operational + state. + properties: + lastTransitionTime: + description: |- + Last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when + the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + A human readable message indicating details about the transition. + This field may be empty. + type: string + reason: + description: |- + The reason for the condition's last transition in CamelCase. + The specific API may choose whether or not this field is considered a guaranteed API. + This field may not be empty. + type: string + severity: + description: |- + Severity provides an explicit classification of Reason code, so the users or machines can immediately + understand the current situation and act accordingly. + The Severity field MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: |- + Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability to deconflict is important. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + lastProxyHeartbeatTime: + description: A timestamp indicating when the proxy last reported status. + format: date-time + type: string + phase: + default: Initializing + description: Phase of the cluster proxy (Initializing, Ready). + enum: + - Initializing + - Connecting + - Ready + - Unknown + type: string + secretString: + description: SecretString is mountpoint secret string for clients to + mount. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/contrib/mounts-virtualworkspace/config/mounts/resources/apiresourceschema-targetkubeclusters.targets.contrib.kcp.io.yaml b/contrib/mounts-virtualworkspace/config/mounts/resources/apiresourceschema-targetkubeclusters.targets.contrib.kcp.io.yaml new file mode 100644 index 00000000000..af17025c593 --- /dev/null +++ b/contrib/mounts-virtualworkspace/config/mounts/resources/apiresourceschema-targetkubeclusters.targets.contrib.kcp.io.yaml @@ -0,0 +1,168 @@ +apiVersion: apis.kcp.io/v1alpha1 +kind: APIResourceSchema +metadata: + creationTimestamp: null + name: v241029-8967b5418.targetkubeclusters.targets.contrib.kcp.io +spec: + group: targets.contrib.kcp.io + names: + categories: + - contrib + kind: TargetKubeCluster + listKind: TargetKubeClusterList + plural: targetkubeclusters + singular: targetkubecluster + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="ClusterReady")].status + name: Ready + type: string + - jsonPath: .status.phase + name: Phase + type: string + name: v1alpha1 + schema: + description: KubeCluster describes the current KubeCluster target object. + properties: + apiVersion: + 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 + kind: + 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 + metadata: + type: object + spec: + description: TargetKubeClusterSpec is the specification of the Target Kube + cluster proxy resource. + properties: + secretRef: + description: SecretRef is a reference to the secret containing the kubeconfig + for the target cluster. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + type: object + status: + description: TargetKubeClusterStatus communicates the observed state of + the Kube cluster proxy. + properties: + URL: + description: URL is the address under which mount should be using. + type: string + conditions: + description: Current processing state of the Cluster proxy. + items: + description: Condition defines an observation of a object operational + state. + properties: + lastTransitionTime: + description: |- + Last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when + the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + A human readable message indicating details about the transition. + This field may be empty. + type: string + reason: + description: |- + The reason for the condition's last transition in CamelCase. + The specific API may choose whether or not this field is considered a guaranteed API. + This field may not be empty. + type: string + severity: + description: |- + Severity provides an explicit classification of Reason code, so the users or machines can immediately + understand the current situation and act accordingly. + The Severity field MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: |- + Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability to deconflict is important. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + lastProxyHeartbeatTime: + description: A timestamp indicating when the proxy last reported status. + format: date-time + type: string + phase: + default: Initializing + description: Phase of the cluster proxy (Initializing, Ready). + enum: + - Initializing + - Connecting + - Ready + - Unknown + type: string + secretString: + description: SecretString is mountpoint secret string for clients to + mount. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/contrib/mounts-virtualworkspace/config/mounts/resources/apiresourceschema-targetvclusters.targets.contrib.kcp.io.yaml b/contrib/mounts-virtualworkspace/config/mounts/resources/apiresourceschema-targetvclusters.targets.contrib.kcp.io.yaml new file mode 100644 index 00000000000..d8304dd1db3 --- /dev/null +++ b/contrib/mounts-virtualworkspace/config/mounts/resources/apiresourceschema-targetvclusters.targets.contrib.kcp.io.yaml @@ -0,0 +1,168 @@ +apiVersion: apis.kcp.io/v1alpha1 +kind: APIResourceSchema +metadata: + creationTimestamp: null + name: v241029-8967b5418.targetvclusters.targets.contrib.kcp.io +spec: + group: targets.contrib.kcp.io + names: + categories: + - contrib + kind: TargetVCluster + listKind: TargetVClusterList + plural: targetvclusters + singular: targetvcluster + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="ClusterReady")].status + name: Ready + type: string + - jsonPath: .status.phase + name: Phase + type: string + name: v1alpha1 + schema: + description: TargetVCluster describes the current VCluster target object. + properties: + apiVersion: + 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 + kind: + 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 + metadata: + type: object + spec: + description: TargetVClusterSpec is the specification of the Target Kube + cluster proxy resource. + properties: + secretRef: + description: SecretRef is a reference to the secret containing the kubeconfig + for the target cluster. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + type: object + status: + description: TargetVClusterStatus communicates the observed state of the + Kube cluster proxy. + properties: + URL: + description: URL is the address under which mount should be using. + type: string + conditions: + description: Current processing state of the Cluster proxy. + items: + description: Condition defines an observation of a object operational + state. + properties: + lastTransitionTime: + description: |- + Last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when + the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + A human readable message indicating details about the transition. + This field may be empty. + type: string + reason: + description: |- + The reason for the condition's last transition in CamelCase. + The specific API may choose whether or not this field is considered a guaranteed API. + This field may not be empty. + type: string + severity: + description: |- + Severity provides an explicit classification of Reason code, so the users or machines can immediately + understand the current situation and act accordingly. + The Severity field MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: |- + Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability to deconflict is important. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + lastProxyHeartbeatTime: + description: A timestamp indicating when the proxy last reported status. + format: date-time + type: string + phase: + default: Initializing + description: Phase of the cluster proxy (Initializing, Ready). + enum: + - Initializing + - Connecting + - Ready + - Unknown + type: string + secretString: + description: SecretString is mountpoint secret string for clients to + mount. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/contrib/mounts-virtualworkspace/config/mounts/resources/apiresourceschema-vclusters.mounts.contrib.kcp.io.yaml b/contrib/mounts-virtualworkspace/config/mounts/resources/apiresourceschema-vclusters.mounts.contrib.kcp.io.yaml new file mode 100644 index 00000000000..d49e7380ed9 --- /dev/null +++ b/contrib/mounts-virtualworkspace/config/mounts/resources/apiresourceschema-vclusters.mounts.contrib.kcp.io.yaml @@ -0,0 +1,188 @@ +apiVersion: apis.kcp.io/v1alpha1 +kind: APIResourceSchema +metadata: + creationTimestamp: null + name: v241101-d11f156a5.vclusters.mounts.contrib.kcp.io +spec: + group: mounts.contrib.kcp.io + names: + categories: + - contrib + kind: VCluster + listKind: VClusterList + plural: vclusters + singular: vcluster + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="ClusterReady")].status + name: Ready + type: string + - jsonPath: .status.phase + name: Phase + type: string + name: v1alpha1 + schema: + description: VCluster describes the current VCluster proxy object. + properties: + apiVersion: + 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 + kind: + 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 + metadata: + type: object + spec: + description: VClusterSpec is the specification of the VCluster cluster proxy + resource. + properties: + mode: + default: Delegated + description: Mode is the mode of the KubeCluster proxy(Direct, Delegated). + enum: + - Delegated + type: string + secretRef: + description: |- + SecretRef is a reference to the secret containing the kubeconfig for the target cluster. + Used only in Direct mode. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + secretString: + description: |- + SecretString is used to identify Target cluster in the backend for mount. + Used only in Delegated mode. + type: string + version: + default: 0.20.2 + description: Version is the version of the VCluster proxy. + type: string + type: object + status: + description: VClusterStatus communicates the observed state of the VCluster + cluster proxy. + properties: + URL: + description: |- + url is the address under which the Kubernetes-cluster-like endpoint + can be found. This URL can be used to access the cluster with standard Kubernetes + client libraries and command line tools via proxy. + type: string + conditions: + description: Current processing state of the Cluster proxy. + items: + description: Condition defines an observation of a object operational + state. + properties: + lastTransitionTime: + description: |- + Last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when + the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + A human readable message indicating details about the transition. + This field may be empty. + type: string + reason: + description: |- + The reason for the condition's last transition in CamelCase. + The specific API may choose whether or not this field is considered a guaranteed API. + This field may not be empty. + type: string + severity: + description: |- + Severity provides an explicit classification of Reason code, so the users or machines can immediately + understand the current situation and act accordingly. + The Severity field MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: |- + Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability to deconflict is important. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + lastProxyHeartbeatTime: + description: A timestamp indicating when the proxy last reported status. + format: date-time + type: string + phase: + default: Initializing + description: Phase of the cluster proxy (Initializing, Ready). + enum: + - Initializing + - Connecting + - Ready + - Unknown + type: string + secretString: + description: |- + SecretString is the secret string used to identify the target cluster in the backend for mount. + Used in both codes, as it is used to identify the target cluster in vcluster cluster pool. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/contrib/mounts-virtualworkspace/config/mounts/resources/example-direct-kubecluster.yaml b/contrib/mounts-virtualworkspace/config/mounts/resources/example-direct-kubecluster.yaml new file mode 100644 index 00000000000..d1b984264ce --- /dev/null +++ b/contrib/mounts-virtualworkspace/config/mounts/resources/example-direct-kubecluster.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: mounts.contrib.kcp.io/v1alpha1 +kind: KubeCluster +metadata: + name: proxy-cluster-direct +spec: + secretRef: + name: kind-kubeconfig + namespace: default diff --git a/contrib/mounts-virtualworkspace/config/mounts/resources/example-mount-cluster.yaml b/contrib/mounts-virtualworkspace/config/mounts/resources/example-mount-cluster.yaml new file mode 100644 index 00000000000..bdd9c6e9eb1 --- /dev/null +++ b/contrib/mounts-virtualworkspace/config/mounts/resources/example-mount-cluster.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: mounts.contrib.kcp.io/v1alpha1 +kind: KubeCluster +metadata: + name: proxy-cluster + annotations: + experimental.tenancy.kcp.io/is-mount: "true" +spec: + mode: Delegated + secretString: LADvMHROwSfMiscs diff --git a/contrib/mounts-virtualworkspace/config/mounts/resources/example-mount-vcluster.yaml b/contrib/mounts-virtualworkspace/config/mounts/resources/example-mount-vcluster.yaml new file mode 100644 index 00000000000..ef593a6976a --- /dev/null +++ b/contrib/mounts-virtualworkspace/config/mounts/resources/example-mount-vcluster.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: mounts.contrib.kcp.io/v1alpha1 +kind: VCluster +metadata: + name: virtual-cluster + annotations: + experimental.tenancy.kcp.io/is-mount: "true" +spec: + mode: Delegated + secretString: LADvMHROwSfMiscs diff --git a/contrib/mounts-virtualworkspace/config/mounts/resources/example-target-cluster.yaml b/contrib/mounts-virtualworkspace/config/mounts/resources/example-target-cluster.yaml new file mode 100644 index 00000000000..e71c78cd178 --- /dev/null +++ b/contrib/mounts-virtualworkspace/config/mounts/resources/example-target-cluster.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: targets.contrib.kcp.io/v1alpha1 +kind: TargetKubeCluster +metadata: + name: proxy-cluster +spec: + secretRef: + name: kind-kubeconfig + namespace: default diff --git a/contrib/mounts-virtualworkspace/config/mounts/resources/example-target-vcluster.yaml b/contrib/mounts-virtualworkspace/config/mounts/resources/example-target-vcluster.yaml new file mode 100644 index 00000000000..1b2abcdb0ea --- /dev/null +++ b/contrib/mounts-virtualworkspace/config/mounts/resources/example-target-vcluster.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: targets.contrib.kcp.io/v1alpha1 +kind: TargetVCluster +metadata: + name: proxy-cluster +spec: + secretRef: + name: kind-kubeconfig + namespace: default diff --git a/contrib/mounts-virtualworkspace/config/vcluster/vlcluster.yaml b/contrib/mounts-virtualworkspace/config/vcluster/vlcluster.yaml new file mode 100644 index 00000000000..1a6c86d0098 --- /dev/null +++ b/contrib/mounts-virtualworkspace/config/vcluster/vlcluster.yaml @@ -0,0 +1,23 @@ +controlPlane: + backingStore: # This backing store option is a Pro feature and requires a license. Remove it if you don't have a license. + etcd: + embedded: + enabled: true + ingress: + enabled: true + host: vcluster-k8s-api.example.com +sync: + toHost: + serviceAccounts: + enabled: true + fromHost: + nodes: + enabled: true + clearImageStatus: true +exportKubeConfig: + context: my-vcluster-context + server: https://vcluster-k8s-api.example.com + secret: + name: my-vcluster-kubeconfig + + diff --git a/contrib/mounts-virtualworkspace/go.mod b/contrib/mounts-virtualworkspace/go.mod new file mode 100644 index 00000000000..efb461e25f7 --- /dev/null +++ b/contrib/mounts-virtualworkspace/go.mod @@ -0,0 +1,240 @@ +module github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace + +go 1.23.2 + +replace ( + github.com/kcp-dev/kcp => ../../ + github.com/kcp-dev/kcp/sdk => ../../sdk + k8s.io/api => github.com/kcp-dev/kubernetes/staging/src/k8s.io/api v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/apiextensions-apiserver => github.com/kcp-dev/kubernetes/staging/src/k8s.io/apiextensions-apiserver v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/apimachinery => github.com/kcp-dev/kubernetes/staging/src/k8s.io/apimachinery v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/apiserver => github.com/kcp-dev/kubernetes/staging/src/k8s.io/apiserver v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/cli-runtime => github.com/kcp-dev/kubernetes/staging/src/k8s.io/cli-runtime v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/client-go => github.com/kcp-dev/kubernetes/staging/src/k8s.io/client-go v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/cloud-provider => github.com/kcp-dev/kubernetes/staging/src/k8s.io/cloud-provider v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/cluster-bootstrap => github.com/kcp-dev/kubernetes/staging/src/k8s.io/cluster-bootstrap v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/code-generator => github.com/kcp-dev/kubernetes/staging/src/k8s.io/code-generator v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/component-base => github.com/kcp-dev/kubernetes/staging/src/k8s.io/component-base v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/component-helpers => github.com/kcp-dev/kubernetes/staging/src/k8s.io/component-helpers v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/controller-manager => github.com/kcp-dev/kubernetes/staging/src/k8s.io/controller-manager v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/cri-api => github.com/kcp-dev/kubernetes/staging/src/k8s.io/cri-api v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/cri-client => github.com/kcp-dev/kubernetes/staging/src/k8s.io/cri-client v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/csi-translation-lib => github.com/kcp-dev/kubernetes/staging/src/k8s.io/csi-translation-lib v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/dynamic-resource-allocation => github.com/kcp-dev/kubernetes/staging/src/k8s.io/dynamic-resource-allocation v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/endpointslice => github.com/kcp-dev/kubernetes/staging/src/k8s.io/endpointslice v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/kms => github.com/kcp-dev/kubernetes/staging/src/k8s.io/kms v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/kube-aggregator => github.com/kcp-dev/kubernetes/staging/src/k8s.io/kube-aggregator v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/kube-controller-manager => github.com/kcp-dev/kubernetes/staging/src/k8s.io/kube-controller-manager v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/kube-proxy => github.com/kcp-dev/kubernetes/staging/src/k8s.io/kube-proxy v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/kube-scheduler => github.com/kcp-dev/kubernetes/staging/src/k8s.io/kube-scheduler v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/kubectl => github.com/kcp-dev/kubernetes/staging/src/k8s.io/kubectl v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/kubelet => github.com/kcp-dev/kubernetes/staging/src/k8s.io/kubelet v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/kubernetes => github.com/kcp-dev/kubernetes v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/legacy-cloud-providers => github.com/kcp-dev/kubernetes/staging/src/k8s.io/legacy-cloud-providers v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/metrics => github.com/kcp-dev/kubernetes/staging/src/k8s.io/metrics v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/mount-utils => github.com/kcp-dev/kubernetes/staging/src/k8s.io/mount-utils v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/pod-security-admission => github.com/kcp-dev/kubernetes/staging/src/k8s.io/pod-security-admission v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/sample-apiserver => github.com/kcp-dev/kubernetes/staging/src/k8s.io/sample-apiserver v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/sample-cli-plugin => github.com/kcp-dev/kubernetes/staging/src/k8s.io/sample-cli-plugin v0.0.0-20240918143026-ab5c3a6448cb + k8s.io/sample-controller => github.com/kcp-dev/kubernetes/staging/src/k8s.io/sample-controller v0.0.0-20240918143026-ab5c3a6448cb +) + +require ( + github.com/kcp-dev/apimachinery/v2 v2.0.1-0.20240817110845-a9eb9752bfeb + github.com/kcp-dev/client-go v0.0.0-20240912145314-f5949d81732a + github.com/kcp-dev/kcp v0.26.0 + github.com/kcp-dev/kcp/sdk v0.0.0-00010101000000-000000000000 + github.com/kcp-dev/logicalcluster/v3 v3.0.5 + github.com/mittwald/go-helm-client v0.12.14 + github.com/spf13/cobra v1.8.1 + github.com/spf13/pflag v1.0.6-0.20210604193023-d5e0c0615ace + golang.org/x/sync v0.8.0 + helm.sh/helm/v3 v3.16.1 + k8s.io/api v0.31.1 + k8s.io/apimachinery v0.31.1 + k8s.io/apiserver v0.31.1 + k8s.io/client-go v0.31.1 + k8s.io/code-generator v0.31.0 + k8s.io/component-base v0.31.1 + k8s.io/klog/v2 v2.130.1 + k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 +) + +require ( + dario.cat/mergo v1.0.1 // indirect + github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/MakeNowJust/heredoc v1.0.0 // indirect + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.3.0 // indirect + github.com/Masterminds/sprig/v3 v3.3.0 // indirect + github.com/Masterminds/squirrel v1.5.4 // indirect + github.com/Microsoft/hcsshim v0.11.4 // indirect + github.com/NYTimes/gziphandler v1.1.1 // indirect + github.com/antlr4-go/antlr/v4 v4.13.0 // indirect + github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/blang/semver/v4 v4.0.0 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/chai2010/gettext-go v1.0.2 // indirect + github.com/containerd/containerd v1.7.12 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/coreos/go-oidc v2.2.1+incompatible // indirect + github.com/coreos/go-semver v0.3.1 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/cyphar/filepath-securejoin v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/distribution/reference v0.5.0 // indirect + github.com/docker/cli v25.0.1+incompatible // indirect + github.com/docker/distribution v2.8.3+incompatible // indirect + github.com/docker/docker v25.0.6+incompatible // indirect + github.com/docker/docker-credential-helpers v0.8.0 // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-metrics v0.0.1 // indirect + github.com/emicklei/go-restful/v3 v3.11.1 // indirect + github.com/evanphx/json-patch v5.9.0+incompatible // indirect + github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/go-errors/errors v1.5.1 // indirect + github.com/go-gorp/gorp/v3 v3.1.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-openapi/jsonpointer v0.20.2 // indirect + github.com/go-openapi/jsonreference v0.20.4 // indirect + github.com/go-openapi/swag v0.22.7 // indirect + github.com/gobwas/glob v0.2.3 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/btree v1.1.2 // indirect + github.com/google/cel-go v0.20.1 // indirect + github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/mux v1.8.1 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/gosuri/uitable v0.0.4 // indirect + github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect + github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/huandu/xstrings v1.5.0 // indirect + github.com/imdario/mergo v0.3.16 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jmoiron/sqlx v1.4.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.17.4 // indirect + github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect + github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect + github.com/lib/pq v1.10.9 // indirect + github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/moby/locker v1.0.1 // indirect + github.com/moby/spdystream v0.4.0 // indirect + github.com/moby/sys/mountinfo v0.7.1 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect + github.com/onsi/gomega v1.33.1 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/opencontainers/runc v1.1.13 // indirect + github.com/opencontainers/runtime-spec v1.1.0 // indirect + github.com/opencontainers/selinux v1.11.0 // indirect + github.com/peterbourgon/diskv v2.0.1+incompatible // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pquerna/cachecontrol v0.1.0 // indirect + github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/rivo/uniseg v0.4.4 // indirect + github.com/rubenv/sql-migrate v1.7.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/shopspring/decimal v1.4.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/spf13/cast v1.7.0 // indirect + github.com/stoewer/go-strcase v1.3.0 // indirect + github.com/x448/float16 v0.8.4 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect + github.com/xlab/treeprint v1.2.0 // indirect + go.etcd.io/etcd/api/v3 v3.5.14 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect + go.etcd.io/etcd/client/v3 v3.5.14 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect + go.opentelemetry.io/otel v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/sdk v1.28.0 // indirect + go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.starlark.net v0.0.0-20231121155337-90ade8b19d09 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.26.0 // indirect + golang.org/x/crypto v0.26.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.26.0 // indirect + golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/sys v0.23.0 // indirect + golang.org/x/term v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/grpc v1.65.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect + gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect + gopkg.in/square/go-jose.v2 v2.6.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/apiextensions-apiserver v0.31.1 // indirect + k8s.io/cli-runtime v0.31.1 // indirect + k8s.io/cloud-provider v0.0.0 // indirect + k8s.io/cluster-bootstrap v0.0.0 // indirect + k8s.io/component-helpers v0.0.0 // indirect + k8s.io/controller-manager v0.0.0 // indirect + k8s.io/dynamic-resource-allocation v0.0.0 // indirect + k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 // indirect + k8s.io/kms v0.0.0 // indirect + k8s.io/kube-aggregator v0.0.0 // indirect + k8s.io/kubectl v0.31.0 // indirect + k8s.io/kubelet v0.0.0 // indirect + k8s.io/kubernetes v1.31.0 // indirect + k8s.io/mount-utils v0.0.0 // indirect + k8s.io/pod-security-admission v0.0.0 // indirect + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect + oras.land/oras-go v1.2.5 // indirect + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/kustomize/api v0.17.2 // indirect + sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect +) diff --git a/contrib/mounts-virtualworkspace/go.sum b/contrib/mounts-virtualworkspace/go.sum new file mode 100644 index 00000000000..c057529234f --- /dev/null +++ b/contrib/mounts-virtualworkspace/go.sum @@ -0,0 +1,610 @@ +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= +github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= +github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= +github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= +github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= +github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= +github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= +github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= +github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= +github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= +github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= +github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= +github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= +github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= +github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= +github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= +github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= +github.com/containerd/containerd v1.7.12 h1:+KQsnv4VnzyxWcfO9mlxxELaoztsDEjOuCMPAuPqgU0= +github.com/containerd/containerd v1.7.12/go.mod h1:/5OMpE1p0ylxtEUGY8kuCYkDRzJm9NO1TFMWjUpdevk= +github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= +github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= +github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/cyphar/filepath-securejoin v0.3.1 h1:1V7cHiaW+C+39wEfpH6XlLBQo3j/PciWFrgfCLS8XrE= +github.com/cyphar/filepath-securejoin v0.3.1/go.mod h1:F7i41x/9cBF7lzCrVsYs9fuzwRZm4NQsGTBdpp6mETc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2 h1:aBfCb7iqHmDEIp6fBvC/hQUddQfg+3qdYjwzaiP9Hnc= +github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2/go.mod h1:WHNsWjnIn2V1LYOrME7e8KxSeKunYHsxEm4am0BUtcI= +github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= +github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/cli v25.0.1+incompatible h1:mFpqnrS6Hsm3v1k7Wa/BO23oz0k121MTbTO1lpcGSkU= +github.com/docker/cli v25.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= +github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v25.0.6+incompatible h1:5cPwbwriIcsua2REJe8HqQV+6WlWc1byg2QSXzBxBGg= +github.com/docker/docker v25.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8= +github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/emicklei/go-restful/v3 v3.11.1 h1:S+9bSbua1z3FgCnV0KKOSSZ3mDthb5NyEPL5gEpCvyk= +github.com/emicklei/go-restful/v3 v3.11.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= +github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= +github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI= +github.com/foxcpp/go-mockdns v1.1.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= +github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= +github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= +github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= +github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= +github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU= +github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= +github.com/go-openapi/swag v0.22.7 h1:JWrc1uc/P9cSomxfnsFSVWoE1FW6bNbrVPmpQYpCcR8= +github.com/go-openapi/swag v0.22.7/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k= +github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= +github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84= +github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= +github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= +github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= +github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= +github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= +github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= +github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kcp-dev/apimachinery/v2 v2.0.1-0.20240817110845-a9eb9752bfeb h1:W11F/dp6NdUnHeB0SrpyWLiifRosu1qaMJvdFGGLXc0= +github.com/kcp-dev/apimachinery/v2 v2.0.1-0.20240817110845-a9eb9752bfeb/go.mod h1:mEDD1K5BVUXJ4CP6wcJ0vZUf+7tbFMjkCFzBKsUNj18= +github.com/kcp-dev/client-go v0.0.0-20240912145314-f5949d81732a h1:O9SNM3MqMlwoEAPSWxk/yw4JU211KpVsAFjTXWQcMEk= +github.com/kcp-dev/client-go v0.0.0-20240912145314-f5949d81732a/go.mod h1:h5jC8rEbkyGUgV86+sgtMMcl950ooGzk+iLrQnbCR6o= +github.com/kcp-dev/kubernetes v0.0.0-20240918143026-ab5c3a6448cb h1:Y0q7dUBB2AShwvoHuAb2q/GeCfk5JRnziTy0s/oV+fs= +github.com/kcp-dev/kubernetes v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:oRHZZzd7fEOSk0mY8fxM++8QPpafz47cbtQUxWENogQ= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/api v0.0.0-20240918143026-ab5c3a6448cb h1:6vSaQJE2W9etXQFdHL9xWDUuzv8f8oTZ3tsXBL9UxMU= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/api v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:6X07YVZkpyT/6XVz4cwyYM2oYH3A3k2QR54H7JXMD90= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/apiextensions-apiserver v0.0.0-20240918143026-ab5c3a6448cb h1:ZoC/9f3PdmoNg5nezL/QrSP8S/lE+nvYsRHf6/bP450= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/apiextensions-apiserver v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:8EZw4zqlExmz7lUTE/P7V0vdAyfiYL84i4ZUHY6qyrk= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/apimachinery v0.0.0-20240918143026-ab5c3a6448cb h1:0obIpoEinm9CtUjjPKAZ1vL/c6OrlrlNzUJzjsw3zNE= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/apimachinery v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:5F0wbie5xX1jDEg5sk5dr+KF8rwFkYtZFHDhSF/UsG4= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/apiserver v0.0.0-20240918143026-ab5c3a6448cb h1:1J6FC8pvCrMeWdnM2bbMZuhHGeeLG+JvQ1uUPnwwlC8= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/apiserver v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:EC5je+P5ix2QCV4zbwxlY8Zk5MJe4e1eKXxjCMd/7Eo= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/cli-runtime v0.0.0-20240918143026-ab5c3a6448cb h1:NzycNVl4dZut4sJ1cN7MIH3hV6IEEMUtM0IiFbf1ZzU= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/cli-runtime v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:IH8L/VJclv2sIZ6SrvWe//+HnuExxQakj5YED82eWo0= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/client-go v0.0.0-20240918143026-ab5c3a6448cb h1:yuzQJrRaTpdylN62AQH7IsQth4gf4pSHX/MBcEEcuYw= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/client-go v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:l7HaB8VBHdNA72/wtAohDsemuLiVNdW6hx9lNB5J088= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/cloud-provider v0.0.0-20240918143026-ab5c3a6448cb h1:iU1IOtSALTD1HRO6w/v1rz2Ia5e8AObchFVVa0KibDY= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/cloud-provider v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:Z1By/ZJf4qFPOirsblzPEI/p61GMTqgsLITfY2hffQo= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/cluster-bootstrap v0.0.0-20240918143026-ab5c3a6448cb h1:RTNzkTSbn8QTIsPu+dN6AOhEpkdJyCxBg4G8oReXqSk= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/cluster-bootstrap v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:A1M/anf3QTVOO3C4oma0zIeBekzHJtgO3Ght7QLBOV8= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/code-generator v0.0.0-20240918143026-ab5c3a6448cb h1:tXzwNHi7U49G65ldKyikILcq1Ymni9F8Dho325mrnWw= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/code-generator v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:FeckrMB5SHLGBJWSRr79xheTG7il5LcGhzdx/v88Jus= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/component-base v0.0.0-20240918143026-ab5c3a6448cb h1:5N/enNWDb3CJ5693LevtUb2sdn6l3FpwYl4H9QtehWQ= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/component-base v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:pgdjhgz6QeKjIVxzIYq4JFZ7VBJRutg/n5W9OKX33qA= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/component-helpers v0.0.0-20240918143026-ab5c3a6448cb h1:edIODpJNACZOypwxCCsdIq6RjI3b4CnajhHLsSBrWZc= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/component-helpers v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:Mx6U6lQkq013rHloS+AAq00nd0b3kkI8cuIu+o2SA7g= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/controller-manager v0.0.0-20240918143026-ab5c3a6448cb h1:aImImYvcBW5bikHNI81ZOak9hGa1hrVVNLdVJVwX32U= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/controller-manager v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:Dc3aSKcPoKmbdnOXAHq/V4Bavxxht9+1bTU8R5ap9yM= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/cri-api v0.0.0-20240918143026-ab5c3a6448cb h1:bok0obA6QA9v5V258so92kdwDrB880VMMuDFlzHdxnk= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/cri-api v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:e2pTb6psrP2AtdW24SxJaesf2402rQ0YjNa7qYssoi0= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/cri-client v0.0.0-20240918143026-ab5c3a6448cb h1:Q4XwHSQrBqPbJn4kEd/WnzZq2wD1fap/SWr8FymrDCE= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/cri-client v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:iz2L6DSY4Ur/Bc/gwXkKZlTnkd/97jgITpRAnuZE2jU= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/csi-translation-lib v0.0.0-20240918143026-ab5c3a6448cb h1:Y3NQx3SSq2MnLUTzHl2tvQAqfEGRvAUVGTL82XEO3Ng= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/csi-translation-lib v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:9M1LHui5W3M9sY3jRBxHpPt30VQ+GdJLgWyGH27/DaI= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/dynamic-resource-allocation v0.0.0-20240918143026-ab5c3a6448cb h1:DuKG7XICOWdL8A4K82RIuRML5gNwQS8XcbssEI0C9rA= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/dynamic-resource-allocation v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:85Fs9bUmpkY/tUQh6zXjvI5BbN7EfiQYQGj07Zf9Dg0= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/kms v0.0.0-20240918143026-ab5c3a6448cb h1:R9utUkok9aychTtScqCgx3++UgkrFROQLwSviwYlVxU= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/kms v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:gClzb5q8LLAagWlaL9S/rt8IcU3iY6gRARKN09DY4o8= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/kube-aggregator v0.0.0-20240918143026-ab5c3a6448cb h1:pkKGAfRuMVinPSEMoj9rKGXCS6+tQ+gPuIlLRCpVn04= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/kube-aggregator v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:npcdPN5G2BMexN5GsPN/xjRN57Ars6h7O7wpjjLJuck= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/kubectl v0.0.0-20240918143026-ab5c3a6448cb h1:8z/JsUTxMBGoTCaJ9is0l+UchpKpokyoEUqWA1p/5xA= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/kubectl v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:rM9967IfBWL2UAhZMoTJRXDZb1ADQFUgILlJvYWZnoQ= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/kubelet v0.0.0-20240918143026-ab5c3a6448cb h1:8obYE0YRPZ15LdG1fryD0fdoXFWmdvkYf7T3aXB+J5s= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/kubelet v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:W3k9YOX2gYkx8IbOyQ9mTgWjJHqIZ6/2fBVKLQOiW/E= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/mount-utils v0.0.0-20240918143026-ab5c3a6448cb h1:f8WXdnBTGh1nm3zUbqqocKYj+LjNuF3fE1BbyQLtWcQ= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/mount-utils v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:p5r0u2M9KzooTgHDz4zRsUt02y4Yx7/5uPwgr0nSGqg= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/pod-security-admission v0.0.0-20240918143026-ab5c3a6448cb h1:aRyoWEKViBwukoJgNi3pbolQO/N6Ljb+jLPihjigusk= +github.com/kcp-dev/kubernetes/staging/src/k8s.io/pod-security-admission v0.0.0-20240918143026-ab5c3a6448cb/go.mod h1:kgTU85Q97g45QWn61Zi55b8iDTap0ZcsXxRSlUMt8o4= +github.com/kcp-dev/logicalcluster/v3 v3.0.5 h1:JbYakokb+5Uinz09oTXomSUJVQsqfxEvU4RyHUYxHOU= +github.com/kcp-dev/logicalcluster/v3 v3.0.5/go.mod h1:EWBUBxdr49fUB1cLMO4nOdBWmYifLbP1LfoL20KkXYY= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= +github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mittwald/go-helm-client v0.12.14 h1:az3GJ4kRmFK609Ic3iHXveNtg92n9jWG0YpKKTIK4oo= +github.com/mittwald/go-helm-client v0.12.14/go.mod h1:2VogAupgnV7FiuoPqtpCYKS/RrMh9fFA3/pD/OmTaLc= +github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= +github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= +github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g= +github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= +github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= +github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= +github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/opencontainers/runc v1.1.13 h1:98S2srgG9vw0zWcDpFMn5TRrh8kLxa/5OFUstuUhmRs= +github.com/opencontainers/runc v1.1.13/go.mod h1:R016aXacfp/gwQBYw2FDGa9m+n6atbLWrYY8hNMT/sA= +github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg= +github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= +github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= +github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= +github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= +github.com/pquerna/cachecontrol v0.1.0 h1:yJMy84ti9h/+OEWa752kBTKv4XC30OtVVHYv/8cTqKc= +github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rubenv/sql-migrate v1.7.0 h1:HtQq1xyTN2ISmQDggnh0c9U3JlP8apWh8YO2jzlXpTI= +github.com/rubenv/sql-migrate v1.7.0/go.mod h1:S4wtDEG1CKn+0ShpTtzWhFpHHI5PvCUtiGI+C+Z2THE= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= +github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= +github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.6-0.20210604193023-d5e0c0615ace h1:9PNP1jnUjRhfmGMlkXHjYPishpcw4jpSt/V/xYY3FMA= +github.com/spf13/pflag v1.0.6-0.20210604193023-d5e0c0615ace/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= +github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE= +github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= +github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= +go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= +go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= +go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0= +go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU= +go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ= +go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= +go.etcd.io/etcd/client/v2 v2.305.13 h1:RWfV1SX5jTU0lbCvpVQe3iPQeAHETWdOTb6pxhd77C8= +go.etcd.io/etcd/client/v2 v2.305.13/go.mod h1:iQnL7fepbiomdXMb3om1rHq96htNNGv2sJkEcZGDRRg= +go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg= +go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= +go.etcd.io/etcd/pkg/v3 v3.5.13 h1:st9bDWNsKkBNpP4PR1MvM/9NqUPfvYZx/YXegsYEH8M= +go.etcd.io/etcd/pkg/v3 v3.5.13/go.mod h1:N+4PLrp7agI/Viy+dUYpX7iRtSPvKq+w8Y14d1vX+m0= +go.etcd.io/etcd/raft/v3 v3.5.13 h1:7r/NKAOups1YnKcfro2RvGGo2PTuizF/xh26Z2CTAzA= +go.etcd.io/etcd/raft/v3 v3.5.13/go.mod h1:uUFibGLn2Ksm2URMxN1fICGhk8Wu96EfDQyuLhAcAmw= +go.etcd.io/etcd/server/v3 v3.5.13 h1:V6KG+yMfMSqWt+lGnhFpP5z5dRUj1BDRJ5k1fQ9DFok= +go.etcd.io/etcd/server/v3 v3.5.13/go.mod h1:K/8nbsGupHqmr5MkgaZpLlH1QdX1pcNQLAkODy44XcQ= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= +go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.starlark.net v0.0.0-20231121155337-90ade8b19d09 h1:hzy3LFnSN8kuQK8h9tHl4ndF6UruMj47OqwqsS+/Ai4= +go.starlark.net v0.0.0-20231121155337-90ade8b19d09/go.mod h1:LcLNIzVOMp4oV+uusnpk+VU+SzXaJakUuBjoCSWH5dM= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY= +google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= +google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw= +google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= +gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= +gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= +helm.sh/helm/v3 v3.16.1 h1:cER6tI/8PgUAsaJaQCVBUg3VI9KN4oVaZJgY60RIc0c= +helm.sh/helm/v3 v3.16.1/go.mod h1:r+xBHHP20qJeEqtvBXMf7W35QDJnzY/eiEBzt+TfHps= +k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 h1:NGrVE502P0s0/1hudf8zjgwki1X/TByhmAoILTarmzo= +k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70/go.mod h1:VH3AT8AaQOqiGjMF9p0/IM1Dj+82ZwjfxUP1IxaHE+8= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= +oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 h1:2770sDpzrjjsAtVhSeUFseziht227YAWYHLGNM8QPwY= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/kustomize/api v0.17.2 h1:E7/Fjk7V5fboiuijoZHgs4aHuexi5Y2loXlVOAVAG5g= +sigs.k8s.io/kustomize/api v0.17.2/go.mod h1:UWTz9Ct+MvoeQsHcJ5e+vziRRkwimm3HytpZgIYqye0= +sigs.k8s.io/kustomize/kyaml v0.17.1 h1:TnxYQxFXzbmNG6gOINgGWQt09GghzgTP6mIurOgrLCQ= +sigs.k8s.io/kustomize/kyaml v0.17.1/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/contrib/mounts-virtualworkspace/hack/boilerplate/boilerplate.Dockerfile.txt b/contrib/mounts-virtualworkspace/hack/boilerplate/boilerplate.Dockerfile.txt new file mode 100644 index 00000000000..ba9ca5fe8d0 --- /dev/null +++ b/contrib/mounts-virtualworkspace/hack/boilerplate/boilerplate.Dockerfile.txt @@ -0,0 +1,16 @@ +# syntax=docker/dockerfile:1.4 + +# Copyright YEAR 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. + diff --git a/contrib/mounts-virtualworkspace/hack/boilerplate/boilerplate.Makefile.txt b/contrib/mounts-virtualworkspace/hack/boilerplate/boilerplate.Makefile.txt new file mode 100644 index 00000000000..16845c7fea3 --- /dev/null +++ b/contrib/mounts-virtualworkspace/hack/boilerplate/boilerplate.Makefile.txt @@ -0,0 +1,14 @@ +# Copyright YEAR 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. + diff --git a/contrib/mounts-virtualworkspace/hack/boilerplate/boilerplate.generatego.txt b/contrib/mounts-virtualworkspace/hack/boilerplate/boilerplate.generatego.txt new file mode 100644 index 00000000000..2d3aa5143d3 --- /dev/null +++ b/contrib/mounts-virtualworkspace/hack/boilerplate/boilerplate.generatego.txt @@ -0,0 +1,16 @@ +/* +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. +*/ + diff --git a/contrib/mounts-virtualworkspace/hack/boilerplate/boilerplate.go.txt b/contrib/mounts-virtualworkspace/hack/boilerplate/boilerplate.go.txt new file mode 100644 index 00000000000..f6d7ed8445d --- /dev/null +++ b/contrib/mounts-virtualworkspace/hack/boilerplate/boilerplate.go.txt @@ -0,0 +1,16 @@ +/* +Copyright YEAR 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. +*/ + diff --git a/contrib/mounts-virtualworkspace/hack/boilerplate/boilerplate.py.txt b/contrib/mounts-virtualworkspace/hack/boilerplate/boilerplate.py.txt new file mode 100644 index 00000000000..16845c7fea3 --- /dev/null +++ b/contrib/mounts-virtualworkspace/hack/boilerplate/boilerplate.py.txt @@ -0,0 +1,14 @@ +# Copyright YEAR 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. + diff --git a/contrib/mounts-virtualworkspace/hack/boilerplate/boilerplate.sh.txt b/contrib/mounts-virtualworkspace/hack/boilerplate/boilerplate.sh.txt new file mode 100644 index 00000000000..16845c7fea3 --- /dev/null +++ b/contrib/mounts-virtualworkspace/hack/boilerplate/boilerplate.sh.txt @@ -0,0 +1,14 @@ +# Copyright YEAR 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. + diff --git a/contrib/mounts-virtualworkspace/hack/go-install.sh b/contrib/mounts-virtualworkspace/hack/go-install.sh new file mode 100755 index 00000000000..453e4bb64f5 --- /dev/null +++ b/contrib/mounts-virtualworkspace/hack/go-install.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash + +# Copyright 2023 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. + +# Originally copied from +# https://github.com/kubernetes-sigs/cluster-api-provider-gcp/blob/c26a68b23e9317323d5d37660fe9d29b3d2ff40c/scripts/go_install.sh + +set -o errexit +set -o nounset +set -o pipefail + +if [[ -z "${1:-}" ]]; then + echo "must provide module as first parameter" + exit 1 +fi + +if [[ -z "${2:-}" ]]; then + echo "must provide binary name as second parameter" + exit 1 +fi + +if [[ -z "${3:-}" ]]; then + echo "must provide version as third parameter" + exit 1 +fi + +if [[ -z "${GOBIN:-}" ]]; then + echo "GOBIN is not set. Must set GOBIN to install the bin in a specified directory." + exit 1 +fi + +mkdir -p "${GOBIN}" + +tmp_dir=$(mktemp -d -t goinstall_XXXXXXXXXX) +function clean { + rm -rf "${tmp_dir}" +} +trap clean EXIT + +rm "${GOBIN}/${2}"* > /dev/null 2>&1 || true + +cd "${tmp_dir}" + +# create a new module in the tmp directory +go mod init fake/mod + +# install the golang module specified as the first argument +go install -tags kcptools "${1}@${3}" +mv "${GOBIN}/${2}" "${GOBIN}/${2}-${3}" +ln -sf "${GOBIN}/${2}-${3}" "${GOBIN}/${2}" diff --git a/contrib/mounts-virtualworkspace/hack/tools.go b/contrib/mounts-virtualworkspace/hack/tools.go new file mode 100644 index 00000000000..53041613ce5 --- /dev/null +++ b/contrib/mounts-virtualworkspace/hack/tools.go @@ -0,0 +1,29 @@ +//go:build kcptools +// +build kcptools + +/* +Copyright 2023 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 tools + +// This package imports things required by this repository, to force `go mod` to see them as dependencies +import ( + _ "k8s.io/code-generator/cmd/applyconfiguration-gen" + _ "k8s.io/code-generator/cmd/client-gen" + _ "k8s.io/code-generator/cmd/deepcopy-gen" + _ "k8s.io/code-generator/cmd/informer-gen" + _ "k8s.io/code-generator/cmd/lister-gen" +) diff --git a/contrib/mounts-virtualworkspace/hack/update-codegen-clients.sh b/contrib/mounts-virtualworkspace/hack/update-codegen-clients.sh new file mode 100755 index 00000000000..162e216452a --- /dev/null +++ b/contrib/mounts-virtualworkspace/hack/update-codegen-clients.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash + +# Copyright 2023 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. + +set -o errexit +set -o nounset +set -o pipefail +set -o xtrace + +export GOPATH=$(go env GOPATH) + +SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. +pushd "${SCRIPT_ROOT}" +BOILERPLATE_HEADER="$( pwd )/hack/boilerplate/boilerplate.go.txt" +popd +CODEGEN_PKG=${CODEGEN_PKG:-$(cd "${SCRIPT_ROOT}"; go list -f '{{.Dir}}' -m k8s.io/code-generator)} +OPENAPI_PKG=${OPENAPI_PKG:-$(cd "${SCRIPT_ROOT}"; go list -f '{{.Dir}}' -m k8s.io/kube-openapi)} + + +# TODO: use generate-groups.sh directly instead once https://github.com/kubernetes/kubernetes/pull/114987 is available +go install "${CODEGEN_PKG}"/cmd/applyconfiguration-gen +go install "${CODEGEN_PKG}"/cmd/client-gen + +# TODO: This is hack to allow CI to pass +chmod +x "${CODEGEN_PKG}"/generate-internal-groups.sh + +source "${CODEGEN_PKG}/kube_codegen.sh" + +"$GOPATH"/bin/applyconfiguration-gen \ + --go-header-file ./hack/boilerplate/boilerplate.generatego.txt \ + --output-pkg github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration \ + --output-dir "${SCRIPT_ROOT}/client/applyconfiguration" \ + github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1 \ + github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1 \ + github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1 \ + k8s.io/apimachinery/pkg/apis/meta/v1 \ + k8s.io/apimachinery/pkg/runtime \ + k8s.io/apimachinery/pkg/version + +"$GOPATH"/bin/client-gen \ + --input github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1 \ + --input github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1 \ + --input-base="" \ + --apply-configuration-package=github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration \ + --clientset-name "versioned" \ + --output-pkg github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset \ + --go-header-file ./hack/boilerplate/boilerplate.generatego.txt \ + --output-dir "${SCRIPT_ROOT}/client/clientset" + +kube::codegen::gen_helpers \ + --boilerplate "${SCRIPT_ROOT}"/hack/boilerplate/boilerplate.generatego.txt \ + ./apis + +echo "$BOILERPLATE_HEADER" +pushd ./apis +${CODE_GENERATOR} \ + "client:outputPackagePath=github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client,apiPackagePath=github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis,singleClusterClientPackagePath=github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned,singleClusterApplyConfigurationsPackagePath=github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/applyconfiguration,headerFile=${BOILERPLATE_HEADER}" \ + "lister:apiPackagePath=github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis,headerFile=${BOILERPLATE_HEADER}" \ + "informer:outputPackagePath=github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client,singleClusterClientPackagePath=github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned,apiPackagePath=github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis,headerFile=${BOILERPLATE_HEADER}" \ + "paths=./..." \ + "output:dir=./../client" +popd + +go install "${OPENAPI_PKG}"/cmd/openapi-gen + +"$GOPATH"/bin/openapi-gen \ + --output-pkg github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/openapi \ + --go-header-file ./hack/boilerplate/boilerplate.generatego.txt \ + --output-dir "${SCRIPT_ROOT}/openapi" \ + github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1 \ + github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1 \ + github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1 \ + k8s.io/apimachinery/pkg/apis/meta/v1 \ + k8s.io/apimachinery/pkg/runtime \ + k8s.io/apimachinery/pkg/version diff --git a/contrib/mounts-virtualworkspace/hack/update-codegen-crds.sh b/contrib/mounts-virtualworkspace/hack/update-codegen-crds.sh new file mode 100755 index 00000000000..01d979ecaab --- /dev/null +++ b/contrib/mounts-virtualworkspace/hack/update-codegen-crds.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash + +# Copyright 2023 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. + +set -o errexit +set -o nounset +set -o pipefail +set -o xtrace + +if [[ -z "${CONTROLLER_GEN:-}" ]]; then + echo "You must either set CONTROLLER_GEN to the path to controller-gen or invoke via make" + exit 1 +fi + +REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) + +# Update generated CRD YAML +( + cd "${REPO_ROOT}/apis" + "../${CONTROLLER_GEN}" \ + crd \ + rbac:roleName=manager-role \ + webhook \ + paths="./..." \ + output:crd:artifacts:config="${REPO_ROOT}"/config/crds +) + +for CRD in "${REPO_ROOT}"/config/crds/*.yaml; do + if [ -f "${CRD}-patch" ]; then + echo "Applying ${CRD}" + ${YAML_PATCH} -o "${CRD}-patch" < "${CRD}" > "${CRD}.patched" + mv "${CRD}.patched" "${CRD}" + fi +done + +( + ${KCP_APIGEN_GEN} --input-dir "${REPO_ROOT}"/config/crds --output-dir "${REPO_ROOT}"/config/mounts/resources +) diff --git a/contrib/mounts-virtualworkspace/hack/verify-go-modules.sh b/contrib/mounts-virtualworkspace/hack/verify-go-modules.sh new file mode 100755 index 00000000000..401b81197f6 --- /dev/null +++ b/contrib/mounts-virtualworkspace/hack/verify-go-modules.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +# Copyright 2023 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. + +# This script verifies all go modules in the repository. + +set -o errexit +set -o nounset +set -o pipefail + +REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) + +mapfile -t DIRS < <(find "${REPO_ROOT}" -name go.mod -print0 | xargs -0 dirname) + +for dir in "${DIRS[@]}"; do + ( + cd "$dir" + echo "Verifying ${dir}" + if ! git diff --quiet HEAD -- go.mod go.sum; then + echo "go module files are out of date" + git diff HEAD -- go.mod go.sum + exit 1 + fi + ) +done diff --git a/contrib/mounts-virtualworkspace/hack/verify-go-versions.sh b/contrib/mounts-virtualworkspace/hack/verify-go-versions.sh new file mode 100755 index 00000000000..f5c46a48ecc --- /dev/null +++ b/contrib/mounts-virtualworkspace/hack/verify-go-versions.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# Copyright 2023 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. + +set -e +set -o pipefail + +VERSION=$(grep "go 1." go.mod | sed 's/go //') + +if [ -z "${IGNORE_GO_VERSION}" ]; then + go version | { ! grep -v go${VERSION}; } || { echo "Unexpected go version installed, expected ${VERSION}. Use IGNORE_GO_VERSION=1 to skip this check."; exit 1; } +fi diff --git a/contrib/mounts-virtualworkspace/openapi/generated.openapi.go b/contrib/mounts-virtualworkspace/openapi/generated.openapi.go new file mode 100644 index 00000000000..7317b0223f8 --- /dev/null +++ b/contrib/mounts-virtualworkspace/openapi/generated.openapi.go @@ -0,0 +1,3480 @@ +//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 openapi-gen. DO NOT EDIT. + +package openapi + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + common "k8s.io/kube-openapi/pkg/common" + spec "k8s.io/kube-openapi/pkg/validation/spec" +) + +func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { + return map[string]common.OpenAPIDefinition{ + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.KubeCluster": schema_mounts_vw_apis_mounts_v1alpha1_KubeCluster(ref), + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.KubeClusterList": schema_mounts_vw_apis_mounts_v1alpha1_KubeClusterList(ref), + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.KubeClusterSpec": schema_mounts_vw_apis_mounts_v1alpha1_KubeClusterSpec(ref), + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.KubeClusterStatus": schema_mounts_vw_apis_mounts_v1alpha1_KubeClusterStatus(ref), + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.VCluster": schema_mounts_vw_apis_mounts_v1alpha1_VCluster(ref), + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.VClusterList": schema_mounts_vw_apis_mounts_v1alpha1_VClusterList(ref), + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.VClusterSpec": schema_mounts_vw_apis_mounts_v1alpha1_VClusterSpec(ref), + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.VClusterStatus": schema_mounts_vw_apis_mounts_v1alpha1_VClusterStatus(ref), + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetKubeCluster": schema_mounts_vw_apis_targets_v1alpha1_TargetKubeCluster(ref), + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetKubeClusterList": schema_mounts_vw_apis_targets_v1alpha1_TargetKubeClusterList(ref), + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetKubeClusterSpec": schema_mounts_vw_apis_targets_v1alpha1_TargetKubeClusterSpec(ref), + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetKubeClusterStatus": schema_mounts_vw_apis_targets_v1alpha1_TargetKubeClusterStatus(ref), + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetVCluster": schema_mounts_vw_apis_targets_v1alpha1_TargetVCluster(ref), + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetVClusterList": schema_mounts_vw_apis_targets_v1alpha1_TargetVClusterList(ref), + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetVClusterSpec": schema_mounts_vw_apis_targets_v1alpha1_TargetVClusterSpec(ref), + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetVClusterStatus": schema_mounts_vw_apis_targets_v1alpha1_TargetVClusterStatus(ref), + "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1.Condition": schema_conditions_apis_conditions_v1alpha1_Condition(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.APIGroup": schema_pkg_apis_meta_v1_APIGroup(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.APIGroupList": schema_pkg_apis_meta_v1_APIGroupList(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.APIResource": schema_pkg_apis_meta_v1_APIResource(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.APIResourceList": schema_pkg_apis_meta_v1_APIResourceList(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.APIVersions": schema_pkg_apis_meta_v1_APIVersions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.ApplyOptions": schema_pkg_apis_meta_v1_ApplyOptions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.Condition": schema_pkg_apis_meta_v1_Condition(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.CreateOptions": schema_pkg_apis_meta_v1_CreateOptions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.DeleteOptions": schema_pkg_apis_meta_v1_DeleteOptions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.Duration": schema_pkg_apis_meta_v1_Duration(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.FieldSelectorRequirement": schema_pkg_apis_meta_v1_FieldSelectorRequirement(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.FieldsV1": schema_pkg_apis_meta_v1_FieldsV1(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.GetOptions": schema_pkg_apis_meta_v1_GetOptions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.GroupKind": schema_pkg_apis_meta_v1_GroupKind(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.GroupResource": schema_pkg_apis_meta_v1_GroupResource(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersion": schema_pkg_apis_meta_v1_GroupVersion(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersionForDiscovery": schema_pkg_apis_meta_v1_GroupVersionForDiscovery(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersionKind": schema_pkg_apis_meta_v1_GroupVersionKind(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersionResource": schema_pkg_apis_meta_v1_GroupVersionResource(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.InternalEvent": schema_pkg_apis_meta_v1_InternalEvent(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector": schema_pkg_apis_meta_v1_LabelSelector(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelectorRequirement": schema_pkg_apis_meta_v1_LabelSelectorRequirement(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.List": schema_pkg_apis_meta_v1_List(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta": schema_pkg_apis_meta_v1_ListMeta(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.ListOptions": schema_pkg_apis_meta_v1_ListOptions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.ManagedFieldsEntry": schema_pkg_apis_meta_v1_ManagedFieldsEntry(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.MicroTime": schema_pkg_apis_meta_v1_MicroTime(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta": schema_pkg_apis_meta_v1_ObjectMeta(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.OwnerReference": schema_pkg_apis_meta_v1_OwnerReference(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.PartialObjectMetadata": schema_pkg_apis_meta_v1_PartialObjectMetadata(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.PartialObjectMetadataList": schema_pkg_apis_meta_v1_PartialObjectMetadataList(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.Patch": schema_pkg_apis_meta_v1_Patch(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.PatchOptions": schema_pkg_apis_meta_v1_PatchOptions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.Preconditions": schema_pkg_apis_meta_v1_Preconditions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.RootPaths": schema_pkg_apis_meta_v1_RootPaths(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.ServerAddressByClientCIDR": schema_pkg_apis_meta_v1_ServerAddressByClientCIDR(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.Status": schema_pkg_apis_meta_v1_Status(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.StatusCause": schema_pkg_apis_meta_v1_StatusCause(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.StatusDetails": schema_pkg_apis_meta_v1_StatusDetails(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.Table": schema_pkg_apis_meta_v1_Table(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.TableColumnDefinition": schema_pkg_apis_meta_v1_TableColumnDefinition(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.TableOptions": schema_pkg_apis_meta_v1_TableOptions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.TableRow": schema_pkg_apis_meta_v1_TableRow(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.TableRowCondition": schema_pkg_apis_meta_v1_TableRowCondition(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.Time": schema_pkg_apis_meta_v1_Time(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.Timestamp": schema_pkg_apis_meta_v1_Timestamp(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.TypeMeta": schema_pkg_apis_meta_v1_TypeMeta(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.UpdateOptions": schema_pkg_apis_meta_v1_UpdateOptions(ref), + "k8s.io/apimachinery/pkg/apis/meta/v1.WatchEvent": schema_pkg_apis_meta_v1_WatchEvent(ref), + "k8s.io/apimachinery/pkg/runtime.RawExtension": schema_k8sio_apimachinery_pkg_runtime_RawExtension(ref), + "k8s.io/apimachinery/pkg/runtime.TypeMeta": schema_k8sio_apimachinery_pkg_runtime_TypeMeta(ref), + "k8s.io/apimachinery/pkg/runtime.Unknown": schema_k8sio_apimachinery_pkg_runtime_Unknown(ref), + "k8s.io/apimachinery/pkg/version.Info": schema_k8sio_apimachinery_pkg_version_Info(ref), + } +} + +func schema_mounts_vw_apis_mounts_v1alpha1_KubeCluster(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "KubeCluster describes the current KubeCluster proxy object.", + 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/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.KubeClusterSpec"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.KubeClusterStatus"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.KubeClusterSpec", "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.KubeClusterStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_mounts_vw_apis_mounts_v1alpha1_KubeClusterList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "KubeClusterList is a list of KubeCluster 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/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.KubeCluster"), + }, + }, + }, + }, + }, + }, + Required: []string{"metadata", "items"}, + }, + }, + Dependencies: []string{ + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.KubeCluster", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_mounts_vw_apis_mounts_v1alpha1_KubeClusterSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "KubeClusterSpec is the specification of the Kube cluster proxy resource.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "mode": { + SchemaProps: spec.SchemaProps{ + Description: "Mode is the mode of the KubeCluster proxy(Direct, Delegated).", + Type: []string{"string"}, + Format: "", + }, + }, + "secretString": { + SchemaProps: spec.SchemaProps{ + Description: "SecretString is used to identify Target cluster in the backend for mount. Used only in Delegated mode.", + Type: []string{"string"}, + Format: "", + }, + }, + "secretRef": { + SchemaProps: spec.SchemaProps{ + Description: "SecretRef is a reference to the secret containing the kubeconfig for the target cluster. Used only in Direct mode.", + Ref: ref("k8s.io/api/core/v1.ObjectReference"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/api/core/v1.ObjectReference"}, + } +} + +func schema_mounts_vw_apis_mounts_v1alpha1_KubeClusterStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "KubeClusterStatus communicates the observed state of the Kube cluster proxy.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "URL": { + SchemaProps: spec.SchemaProps{ + Description: "url is the address under which the Kubernetes-cluster-like endpoint can be found. This URL can be used to access the cluster with standard Kubernetes client libraries and command line tools via proxy.", + Type: []string{"string"}, + Format: "", + }, + }, + "phase": { + SchemaProps: spec.SchemaProps{ + Description: "Phase of the cluster proxy (Initializing, Ready).", + Type: []string{"string"}, + Format: "", + }, + }, + "lastProxyHeartbeatTime": { + SchemaProps: spec.SchemaProps{ + Description: "A timestamp indicating when the proxy last reported status.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + }, + }, + "secretString": { + SchemaProps: spec.SchemaProps{ + Description: "SecretString is mountpoint secret string for clients to mount.", + Type: []string{"string"}, + Format: "", + }, + }, + "conditions": { + SchemaProps: spec.SchemaProps{ + Description: "Current processing state of the Cluster proxy.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1.Condition"), + }, + }, + }, + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, + } +} + +func schema_mounts_vw_apis_mounts_v1alpha1_VCluster(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "VCluster describes the current VCluster proxy object.", + 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/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.VClusterSpec"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.VClusterStatus"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.VClusterSpec", "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.VClusterStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_mounts_vw_apis_mounts_v1alpha1_VClusterList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "VClusterList is a list of VCluster 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/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.VCluster"), + }, + }, + }, + }, + }, + }, + Required: []string{"metadata", "items"}, + }, + }, + Dependencies: []string{ + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1.VCluster", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_mounts_vw_apis_mounts_v1alpha1_VClusterSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "VClusterSpec is the specification of the VCluster cluster proxy resource.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "version": { + SchemaProps: spec.SchemaProps{ + Description: "Version is the version of the VCluster proxy.", + Type: []string{"string"}, + Format: "", + }, + }, + "mode": { + SchemaProps: spec.SchemaProps{ + Description: "Mode is the mode of the KubeCluster proxy(Direct, Delegated).", + Type: []string{"string"}, + Format: "", + }, + }, + "secretString": { + SchemaProps: spec.SchemaProps{ + Description: "SecretString is used to identify Target cluster in the backend for mount. Used only in Delegated mode.", + Type: []string{"string"}, + Format: "", + }, + }, + "secretRef": { + SchemaProps: spec.SchemaProps{ + Description: "SecretRef is a reference to the secret containing the kubeconfig for the target cluster. Used only in Direct mode.", + Ref: ref("k8s.io/api/core/v1.ObjectReference"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/api/core/v1.ObjectReference"}, + } +} + +func schema_mounts_vw_apis_mounts_v1alpha1_VClusterStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "VClusterStatus communicates the observed state of the VCluster cluster proxy.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "URL": { + SchemaProps: spec.SchemaProps{ + Description: "url is the address under which the Kubernetes-cluster-like endpoint can be found. This URL can be used to access the cluster with standard Kubernetes client libraries and command line tools via proxy.", + Type: []string{"string"}, + Format: "", + }, + }, + "secretString": { + SchemaProps: spec.SchemaProps{ + Description: "SecretString is the secret string used to identify the target cluster in the backend for mount. Used in both codes, as it is used to identify the target cluster in vcluster cluster pool.", + Type: []string{"string"}, + Format: "", + }, + }, + "phase": { + SchemaProps: spec.SchemaProps{ + Description: "Phase of the cluster proxy (Initializing, Ready).", + Type: []string{"string"}, + Format: "", + }, + }, + "lastProxyHeartbeatTime": { + SchemaProps: spec.SchemaProps{ + Description: "A timestamp indicating when the proxy last reported status.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + }, + }, + "conditions": { + SchemaProps: spec.SchemaProps{ + Description: "Current processing state of the Cluster proxy.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1.Condition"), + }, + }, + }, + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, + } +} + +func schema_mounts_vw_apis_targets_v1alpha1_TargetKubeCluster(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "KubeCluster describes the current KubeCluster target object.", + 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/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetKubeClusterSpec"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetKubeClusterStatus"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetKubeClusterSpec", "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetKubeClusterStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_mounts_vw_apis_targets_v1alpha1_TargetKubeClusterList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TargetKubeClusterList is a list of TargetKubeCluster 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/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetKubeCluster"), + }, + }, + }, + }, + }, + }, + Required: []string{"metadata", "items"}, + }, + }, + Dependencies: []string{ + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetKubeCluster", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_mounts_vw_apis_targets_v1alpha1_TargetKubeClusterSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TargetKubeClusterSpec is the specification of the Target Kube cluster proxy resource.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "secretRef": { + SchemaProps: spec.SchemaProps{ + Description: "SecretRef is a reference to the secret containing the kubeconfig for the target cluster.", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/api/core/v1.ObjectReference"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/api/core/v1.ObjectReference"}, + } +} + +func schema_mounts_vw_apis_targets_v1alpha1_TargetKubeClusterStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TargetKubeClusterStatus communicates the observed state of the Kube cluster proxy.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "phase": { + SchemaProps: spec.SchemaProps{ + Description: "Phase of the cluster proxy (Initializing, Ready).", + Type: []string{"string"}, + Format: "", + }, + }, + "lastProxyHeartbeatTime": { + SchemaProps: spec.SchemaProps{ + Description: "A timestamp indicating when the proxy last reported status.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + }, + }, + "conditions": { + SchemaProps: spec.SchemaProps{ + Description: "Current processing state of the Cluster proxy.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1.Condition"), + }, + }, + }, + }, + }, + "secretString": { + SchemaProps: spec.SchemaProps{ + Description: "SecretString is mountpoint secret string for clients to mount.", + Type: []string{"string"}, + Format: "", + }, + }, + "URL": { + SchemaProps: spec.SchemaProps{ + Description: "URL is the address under which mount should be using.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, + } +} + +func schema_mounts_vw_apis_targets_v1alpha1_TargetVCluster(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TargetVCluster describes the current VCluster target object.", + 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/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetVClusterSpec"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetVClusterStatus"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetVClusterSpec", "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetVClusterStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_mounts_vw_apis_targets_v1alpha1_TargetVClusterList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TargetVClusterList is a list of TargetVCluster 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/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetVCluster"), + }, + }, + }, + }, + }, + }, + Required: []string{"metadata", "items"}, + }, + }, + Dependencies: []string{ + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1.TargetVCluster", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_mounts_vw_apis_targets_v1alpha1_TargetVClusterSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TargetVClusterSpec is the specification of the Target Kube cluster proxy resource.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "secretRef": { + SchemaProps: spec.SchemaProps{ + Description: "SecretRef is a reference to the secret containing the kubeconfig for the target cluster.", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/api/core/v1.ObjectReference"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/api/core/v1.ObjectReference"}, + } +} + +func schema_mounts_vw_apis_targets_v1alpha1_TargetVClusterStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TargetVClusterStatus communicates the observed state of the Kube cluster proxy.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "phase": { + SchemaProps: spec.SchemaProps{ + Description: "Phase of the cluster proxy (Initializing, Ready).", + Type: []string{"string"}, + Format: "", + }, + }, + "lastProxyHeartbeatTime": { + SchemaProps: spec.SchemaProps{ + Description: "A timestamp indicating when the proxy last reported status.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + }, + }, + "conditions": { + SchemaProps: spec.SchemaProps{ + Description: "Current processing state of the Cluster proxy.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1.Condition"), + }, + }, + }, + }, + }, + "secretString": { + SchemaProps: spec.SchemaProps{ + Description: "SecretString is mountpoint secret string for clients to mount.", + Type: []string{"string"}, + Format: "", + }, + }, + "URL": { + SchemaProps: spec.SchemaProps{ + Description: "URL is the address under which mount should be using.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1.Condition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, + } +} + +func schema_conditions_apis_conditions_v1alpha1_Condition(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Condition defines an observation of a object operational state.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "type": { + SchemaProps: spec.SchemaProps{ + Description: "Type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Description: "Status of the condition, one of True, False, Unknown.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "severity": { + SchemaProps: spec.SchemaProps{ + Description: "Severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False.", + Type: []string{"string"}, + Format: "", + }, + }, + "lastTransitionTime": { + SchemaProps: spec.SchemaProps{ + Description: "Last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + }, + }, + "reason": { + SchemaProps: spec.SchemaProps{ + Description: "The reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may not be empty.", + Type: []string{"string"}, + Format: "", + }, + }, + "message": { + SchemaProps: spec.SchemaProps{ + Description: "A human readable message indicating details about the transition. This field may be empty.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"type", "status", "lastTransitionTime"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, + } +} + +func schema_pkg_apis_meta_v1_APIGroup(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "APIGroup contains the name, the supported versions, and the preferred version of a group.", + 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: "", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Description: "name is the name of the group.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "versions": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "versions are the versions supported in this group.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersionForDiscovery"), + }, + }, + }, + }, + }, + "preferredVersion": { + SchemaProps: spec.SchemaProps{ + Description: "preferredVersion is the version preferred by the API server, which probably is the storage version.", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersionForDiscovery"), + }, + }, + "serverAddressByClientCIDRs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "a map of client CIDR to server address that is serving this group. This is to help clients reach servers in the most network-efficient way possible. Clients can use the appropriate server address as per the CIDR that they match. In case of multiple matches, clients should use the longest matching CIDR. The server returns only those CIDRs that it thinks that the client can match. For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP. Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ServerAddressByClientCIDR"), + }, + }, + }, + }, + }, + }, + Required: []string{"name", "versions"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersionForDiscovery", "k8s.io/apimachinery/pkg/apis/meta/v1.ServerAddressByClientCIDR"}, + } +} + +func schema_pkg_apis_meta_v1_APIGroupList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "APIGroupList is a list of APIGroup, to allow clients to discover the API at /apis.", + 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: "", + }, + }, + "groups": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "groups is a list of APIGroup.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.APIGroup"), + }, + }, + }, + }, + }, + }, + Required: []string{"groups"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.APIGroup"}, + } +} + +func schema_pkg_apis_meta_v1_APIResource(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "APIResource specifies the name of a resource and whether it is namespaced.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Description: "name is the plural name of the resource.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "singularName": { + SchemaProps: spec.SchemaProps{ + Description: "singularName is the singular name of the resource. This allows clients to handle plural and singular opaquely. The singularName is more correct for reporting status on a single item and both singular and plural are allowed from the kubectl CLI interface.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "namespaced": { + SchemaProps: spec.SchemaProps{ + Description: "namespaced indicates if a resource is namespaced or not.", + Default: false, + Type: []string{"boolean"}, + Format: "", + }, + }, + "group": { + SchemaProps: spec.SchemaProps{ + Description: "group is the preferred group of the resource. Empty implies the group of the containing resource list. For subresources, this may have a different value, for example: Scale\".", + Type: []string{"string"}, + Format: "", + }, + }, + "version": { + SchemaProps: spec.SchemaProps{ + Description: "version is the preferred version of the resource. Empty implies the version of the containing resource list For subresources, this may have a different value, for example: v1 (while inside a v1beta1 version of the core resource's group)\".", + Type: []string{"string"}, + Format: "", + }, + }, + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "kind is the kind for the resource (e.g. 'Foo' is the kind for a resource 'foo')", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "verbs": { + SchemaProps: spec.SchemaProps{ + Description: "verbs is a list of supported kube verbs (this includes get, list, watch, create, update, patch, delete, deletecollection, and proxy)", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "shortNames": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "shortNames is a list of suggested short names of the resource.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "categories": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "categories is a list of the grouped resources this resource belongs to (e.g. 'all')", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "storageVersionHash": { + SchemaProps: spec.SchemaProps{ + Description: "The hash value of the storage version, the version this resource is converted to when written to the data store. Value must be treated as opaque by clients. Only equality comparison on the value is valid. This is an alpha feature and may change or be removed in the future. The field is populated by the apiserver only if the StorageVersionHash feature gate is enabled. This field will remain optional even if it graduates.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"name", "singularName", "namespaced", "kind", "verbs"}, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_APIResourceList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "APIResourceList is a list of APIResource, it is used to expose the name of the resources supported in a specific group and version, and if the resource is namespaced.", + 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: "", + }, + }, + "groupVersion": { + SchemaProps: spec.SchemaProps{ + Description: "groupVersion is the group and version this APIResourceList is for.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "resources": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "resources contains the name of the resources and if they are namespaced.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.APIResource"), + }, + }, + }, + }, + }, + }, + Required: []string{"groupVersion", "resources"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.APIResource"}, + } +} + +func schema_pkg_apis_meta_v1_APIVersions(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "APIVersions lists the versions that are available, to allow clients to discover the API at /api, which is the root path of the legacy v1 API.", + 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: "", + }, + }, + "versions": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "versions are the api versions that are available.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "serverAddressByClientCIDRs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "a map of client CIDR to server address that is serving this group. This is to help clients reach servers in the most network-efficient way possible. Clients can use the appropriate server address as per the CIDR that they match. In case of multiple matches, clients should use the longest matching CIDR. The server returns only those CIDRs that it thinks that the client can match. For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP. Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ServerAddressByClientCIDR"), + }, + }, + }, + }, + }, + }, + Required: []string{"versions", "serverAddressByClientCIDRs"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.ServerAddressByClientCIDR"}, + } +} + +func schema_pkg_apis_meta_v1_ApplyOptions(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ApplyOptions may be provided when applying an API object. FieldManager is required for apply requests. ApplyOptions is equivalent to PatchOptions. It is provided as a convenience with documentation that speaks specifically to how the options fields relate to apply.", + 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: "", + }, + }, + "dryRun": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "force": { + SchemaProps: spec.SchemaProps{ + Description: "Force is going to \"force\" Apply requests. It means user will re-acquire conflicting fields owned by other people.", + Default: false, + Type: []string{"boolean"}, + Format: "", + }, + }, + "fieldManager": { + SchemaProps: spec.SchemaProps{ + Description: "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint. This field is required.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"force", "fieldManager"}, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_Condition(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Condition contains details for one aspect of the current state of this API Resource.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "type": { + SchemaProps: spec.SchemaProps{ + Description: "type of condition in CamelCase or in foo.example.com/CamelCase.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Description: "status of the condition, one of True, False, Unknown.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "observedGeneration": { + SchemaProps: spec.SchemaProps{ + Description: "observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "lastTransitionTime": { + SchemaProps: spec.SchemaProps{ + Description: "lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + }, + }, + "reason": { + SchemaProps: spec.SchemaProps{ + Description: "reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "message": { + SchemaProps: spec.SchemaProps{ + Description: "message is a human readable message indicating details about the transition. This may be an empty string.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"type", "status", "lastTransitionTime", "reason", "message"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, + } +} + +func schema_pkg_apis_meta_v1_CreateOptions(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "CreateOptions may be provided when creating an API object.", + 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: "", + }, + }, + "dryRun": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "fieldManager": { + SchemaProps: spec.SchemaProps{ + Description: "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + Type: []string{"string"}, + Format: "", + }, + }, + "fieldValidation": { + SchemaProps: spec.SchemaProps{ + Description: "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default in v1.23+ - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_DeleteOptions(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "DeleteOptions may be provided when deleting an API object.", + 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: "", + }, + }, + "gracePeriodSeconds": { + SchemaProps: spec.SchemaProps{ + Description: "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "preconditions": { + SchemaProps: spec.SchemaProps{ + Description: "Must be fulfilled before a deletion is carried out. If not possible, a 409 Conflict status will be returned.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Preconditions"), + }, + }, + "orphanDependents": { + SchemaProps: spec.SchemaProps{ + Description: "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.", + Type: []string{"boolean"}, + Format: "", + }, + }, + "propagationPolicy": { + SchemaProps: spec.SchemaProps{ + Description: "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.", + Type: []string{"string"}, + Format: "", + }, + }, + "dryRun": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.Preconditions"}, + } +} + +func schema_pkg_apis_meta_v1_Duration(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Duration is a wrapper around time.Duration which supports correct marshaling to YAML and JSON. In particular, it marshals into strings, which can be used as map keys in json.", + Type: v1.Duration{}.OpenAPISchemaType(), + Format: v1.Duration{}.OpenAPISchemaFormat(), + }, + }, + } +} + +func schema_pkg_apis_meta_v1_FieldSelectorRequirement(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "FieldSelectorRequirement is a selector that contains values, a key, and an operator that relates the key and values.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "key": { + SchemaProps: spec.SchemaProps{ + Description: "key is the field selector key that the requirement applies to.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "operator": { + SchemaProps: spec.SchemaProps{ + Description: "operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. The list of operators may grow in the future.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "values": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + }, + Required: []string{"key", "operator"}, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_FieldsV1(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "FieldsV1 stores a set of fields in a data structure like a Trie, in JSON format.\n\nEach key is either a '.' representing the field itself, and will always map to an empty set, or a string representing a sub-field or item. The string will follow one of these four formats: 'f:', where is the name of a field in a struct, or key in a map 'v:', where is the exact json formatted value of a list item 'i:', where is position of a item in a list 'k:', where is a map of a list item's key fields to their unique values If a key maps to an empty Fields value, the field that key represents is part of the set.\n\nThe exact format is defined in sigs.k8s.io/structured-merge-diff", + Type: []string{"object"}, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_GetOptions(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "GetOptions is the standard query options to the standard REST get call.", + 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: "", + }, + }, + "resourceVersion": { + SchemaProps: spec.SchemaProps{ + Description: "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_GroupKind(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "group": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "kind": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"group", "kind"}, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_GroupResource(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "GroupResource specifies a Group and a Resource, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "group": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "resource": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"group", "resource"}, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_GroupVersion(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "GroupVersion contains the \"group\" and the \"version\", which uniquely identifies the API.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "group": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "version": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"group", "version"}, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_GroupVersionForDiscovery(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "GroupVersion contains the \"group/version\" and \"version\" string of a version. It is made a struct to keep extensibility.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "groupVersion": { + SchemaProps: spec.SchemaProps{ + Description: "groupVersion specifies the API group and version in the form \"group/version\"", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "version": { + SchemaProps: spec.SchemaProps{ + Description: "version specifies the version in the form of \"version\". This is to save the clients the trouble of splitting the GroupVersion.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"groupVersion", "version"}, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_GroupVersionKind(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "GroupVersionKind unambiguously identifies a kind. It doesn't anonymously include GroupVersion to avoid automatic coercion. It doesn't use a GroupVersion to avoid custom marshalling", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "group": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "version": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "kind": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"group", "version", "kind"}, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_GroupVersionResource(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "GroupVersionResource unambiguously identifies a resource. It doesn't anonymously include GroupVersion to avoid automatic coercion. It doesn't use a GroupVersion to avoid custom marshalling", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "group": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "version": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "resource": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"group", "version", "resource"}, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_InternalEvent(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "InternalEvent makes watch.Event versioned", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "Type": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "Object": { + SchemaProps: spec.SchemaProps{ + Description: "Object is:\n * If Type is Added or Modified: the new state of the object.\n * If Type is Deleted: the state of the object immediately before deletion.\n * If Type is Bookmark: the object (instance of a type being watched) where\n only ResourceVersion field is set. On successful restart of watch from a\n bookmark resourceVersion, client is guaranteed to not get repeat event\n nor miss any events.\n * If Type is Error: *api.Status is recommended; other types may make sense\n depending on context.", + Ref: ref("k8s.io/apimachinery/pkg/runtime.Object"), + }, + }, + }, + Required: []string{"Type", "Object"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/runtime.Object"}, + } +} + +func schema_pkg_apis_meta_v1_LabelSelector(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "matchLabels": { + SchemaProps: spec.SchemaProps{ + Description: "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is \"key\", the operator is \"In\", and the values array contains only \"value\". The requirements are ANDed.", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "matchExpressions": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "matchExpressions is a list of label selector requirements. The requirements are ANDed.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelectorRequirement"), + }, + }, + }, + }, + }, + }, + }, + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-map-type": "atomic", + }, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelectorRequirement"}, + } +} + +func schema_pkg_apis_meta_v1_LabelSelectorRequirement(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "key": { + SchemaProps: spec.SchemaProps{ + Description: "key is the label key that the selector applies to.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "operator": { + SchemaProps: spec.SchemaProps{ + Description: "operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "values": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + }, + Required: []string{"key", "operator"}, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_List(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "List holds a list of objects, which may not be known by the server.", + 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{ + Description: "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Description: "List of objects", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("k8s.io/apimachinery/pkg/runtime.RawExtension"), + }, + }, + }, + }, + }, + }, + Required: []string{"items"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta", "k8s.io/apimachinery/pkg/runtime.RawExtension"}, + } +} + +func schema_pkg_apis_meta_v1_ListMeta(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ListMeta describes metadata that synthetic resources must have, including lists and various status objects. A resource may have only one of {ObjectMeta, ListMeta}.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "selfLink": { + SchemaProps: spec.SchemaProps{ + Description: "Deprecated: selfLink is a legacy read-only field that is no longer populated by the system.", + Type: []string{"string"}, + Format: "", + }, + }, + "resourceVersion": { + SchemaProps: spec.SchemaProps{ + Description: "String that identifies the server's internal version of this object that can be used by clients to determine when objects have changed. Value must be treated as opaque by clients and passed unmodified back to the server. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency", + Type: []string{"string"}, + Format: "", + }, + }, + "continue": { + SchemaProps: spec.SchemaProps{ + Description: "continue may be set if the user set a limit on the number of items returned, and indicates that the server has more data available. The value is opaque and may be used to issue another request to the endpoint that served this list to retrieve the next set of available objects. Continuing a consistent list may not be possible if the server configuration has changed or more than a few minutes have passed. The resourceVersion field returned when using this continue value will be identical to the value in the first response, unless you have received this token from an error message.", + Type: []string{"string"}, + Format: "", + }, + }, + "remainingItemCount": { + SchemaProps: spec.SchemaProps{ + Description: "remainingItemCount is the number of subsequent items in the list which are not included in this list response. If the list request contained label or field selectors, then the number of remaining items is unknown and the field will be left unset and omitted during serialization. If the list is complete (either because it is not chunking or because this is the last chunk), then there are no more remaining items and this field will be left unset and omitted during serialization. Servers older than v1.15 do not set this field. The intended use of the remainingItemCount is *estimating* the size of a collection. Clients should not rely on the remainingItemCount to be set or to be exact.", + Type: []string{"integer"}, + Format: "int64", + }, + }, + }, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_ListOptions(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ListOptions is the query options to a standard REST list call.", + 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: "", + }, + }, + "labelSelector": { + SchemaProps: spec.SchemaProps{ + Description: "A selector to restrict the list of returned objects by their labels. Defaults to everything.", + Type: []string{"string"}, + Format: "", + }, + }, + "fieldSelector": { + SchemaProps: spec.SchemaProps{ + Description: "A selector to restrict the list of returned objects by their fields. Defaults to everything.", + Type: []string{"string"}, + Format: "", + }, + }, + "watch": { + SchemaProps: spec.SchemaProps{ + Description: "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.", + Type: []string{"boolean"}, + Format: "", + }, + }, + "allowWatchBookmarks": { + SchemaProps: spec.SchemaProps{ + Description: "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored.", + Type: []string{"boolean"}, + Format: "", + }, + }, + "resourceVersion": { + SchemaProps: spec.SchemaProps{ + Description: "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + Type: []string{"string"}, + Format: "", + }, + }, + "resourceVersionMatch": { + SchemaProps: spec.SchemaProps{ + Description: "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset", + Type: []string{"string"}, + Format: "", + }, + }, + "timeoutSeconds": { + SchemaProps: spec.SchemaProps{ + Description: "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "limit": { + SchemaProps: spec.SchemaProps{ + Description: "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "continue": { + SchemaProps: spec.SchemaProps{ + Description: "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.", + Type: []string{"string"}, + Format: "", + }, + }, + "sendInitialEvents": { + SchemaProps: spec.SchemaProps{ + Description: "`sendInitialEvents=true` may be set together with `watch=true`. In that case, the watch stream will begin with synthetic events to produce the current state of objects in the collection. Once all such events have been sent, a synthetic \"Bookmark\" event will be sent. The bookmark will report the ResourceVersion (RV) corresponding to the set of objects, and be marked with `\"k8s.io/initial-events-end\": \"true\"` annotation. Afterwards, the watch stream will proceed as usual, sending watch events corresponding to changes (subsequent to the RV) to objects watched.\n\nWhen `sendInitialEvents` option is set, we require `resourceVersionMatch` option to also be set. The semantic of the watch request is as following: - `resourceVersionMatch` = NotOlderThan\n is interpreted as \"data at least as new as the provided `resourceVersion`\"\n and the bookmark event is send when the state is synced\n to a `resourceVersion` at least as fresh as the one provided by the ListOptions.\n If `resourceVersion` is unset, this is interpreted as \"consistent read\" and the\n bookmark event is send when the state is synced at least to the moment\n when request started being processed.\n- `resourceVersionMatch` set to any other value or unset\n Invalid error is returned.\n\nDefaults to true if `resourceVersion=\"\"` or `resourceVersion=\"0\"` (for backward compatibility reasons) and to false otherwise.", + Type: []string{"boolean"}, + Format: "", + }, + }, + }, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_ManagedFieldsEntry(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ManagedFieldsEntry is a workflow-id, a FieldSet and the group version of the resource that the fieldset applies to.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "manager": { + SchemaProps: spec.SchemaProps{ + Description: "Manager is an identifier of the workflow managing these fields.", + Type: []string{"string"}, + Format: "", + }, + }, + "operation": { + SchemaProps: spec.SchemaProps{ + Description: "Operation is the type of operation which lead to this ManagedFieldsEntry being created. The only valid values for this field are 'Apply' and 'Update'.", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the version of this resource that this field set applies to. The format is \"group/version\" just like the top-level APIVersion field. It is necessary to track the version of a field set because it cannot be automatically converted.", + Type: []string{"string"}, + Format: "", + }, + }, + "time": { + SchemaProps: spec.SchemaProps{ + Description: "Time is the timestamp of when the ManagedFields entry was added. The timestamp will also be updated if a field is added, the manager changes any of the owned fields value or removes a field. The timestamp does not update when a field is removed from the entry because another manager took it over.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + }, + }, + "fieldsType": { + SchemaProps: spec.SchemaProps{ + Description: "FieldsType is the discriminator for the different fields format and version. There is currently only one possible value: \"FieldsV1\"", + Type: []string{"string"}, + Format: "", + }, + }, + "fieldsV1": { + SchemaProps: spec.SchemaProps{ + Description: "FieldsV1 holds the first JSON version format as described in the \"FieldsV1\" type.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.FieldsV1"), + }, + }, + "subresource": { + SchemaProps: spec.SchemaProps{ + Description: "Subresource is the name of the subresource used to update that object, or empty string if the object was updated through the main resource. The value of this field is used to distinguish between managers, even if they share the same name. For example, a status update will be distinct from a regular update using the same manager name. Note that the APIVersion field is not related to the Subresource field and it always corresponds to the version of the main resource.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.FieldsV1", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, + } +} + +func schema_pkg_apis_meta_v1_MicroTime(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "MicroTime is version of Time with microsecond level precision.", + Type: v1.MicroTime{}.OpenAPISchemaType(), + Format: v1.MicroTime{}.OpenAPISchemaFormat(), + }, + }, + } +} + +func schema_pkg_apis_meta_v1_ObjectMeta(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names", + Type: []string{"string"}, + Format: "", + }, + }, + "generateName": { + SchemaProps: spec.SchemaProps{ + Description: "GenerateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server.\n\nIf this field is specified and the generated name exists, the server will return a 409.\n\nApplied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#idempotency", + Type: []string{"string"}, + Format: "", + }, + }, + "namespace": { + SchemaProps: spec.SchemaProps{ + Description: "Namespace defines the space within which each name must be unique. An empty namespace is equivalent to the \"default\" namespace, but \"default\" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty.\n\nMust be a DNS_LABEL. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces", + Type: []string{"string"}, + Format: "", + }, + }, + "selfLink": { + SchemaProps: spec.SchemaProps{ + Description: "Deprecated: selfLink is a legacy read-only field that is no longer populated by the system.", + Type: []string{"string"}, + Format: "", + }, + }, + "uid": { + SchemaProps: spec.SchemaProps{ + Description: "UID is the unique in time and space value for this object. It is typically generated by the server on successful creation of a resource and is not allowed to change on PUT operations.\n\nPopulated by the system. Read-only. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids", + Type: []string{"string"}, + Format: "", + }, + }, + "resourceVersion": { + SchemaProps: spec.SchemaProps{ + Description: "An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources.\n\nPopulated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency", + Type: []string{"string"}, + Format: "", + }, + }, + "generation": { + SchemaProps: spec.SchemaProps{ + Description: "A sequence number representing a specific generation of the desired state. Populated by the system. Read-only.", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "creationTimestamp": { + SchemaProps: spec.SchemaProps{ + Description: "CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC.\n\nPopulated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + }, + }, + "deletionTimestamp": { + SchemaProps: spec.SchemaProps{ + Description: "DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This field is set by the server when a graceful deletion is requested by the user, and is not directly settable by a client. The resource is expected to be deleted (no longer visible from resource lists, and not reachable by name) after the time in this field, once the finalizers list is empty. As long as the finalizers list contains items, deletion is blocked. Once the deletionTimestamp is set, this value may not be unset or be set further into the future, although it may be shortened or the resource may be deleted prior to this time. For example, a user may request that a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination signal to the containers in the pod. After that 30 seconds, the Kubelet will send a hard termination signal (SIGKILL) to the container and after cleanup, remove the pod from the API. In the presence of network partitions, this object may still exist after this timestamp, until an administrator or automated process can determine the resource is fully terminated. If not set, graceful deletion of the object has not been requested.\n\nPopulated by the system when a graceful deletion is requested. Read-only. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), + }, + }, + "deletionGracePeriodSeconds": { + SchemaProps: spec.SchemaProps{ + Description: "Number of seconds allowed for this object to gracefully terminate before it will be removed from the system. Only set when deletionTimestamp is also set. May only be shortened. Read-only.", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "labels": { + SchemaProps: spec.SchemaProps{ + Description: "Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "annotations": { + SchemaProps: spec.SchemaProps{ + Description: "Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "ownerReferences": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-map-keys": []interface{}{ + "uid", + }, + "x-kubernetes-list-type": "map", + "x-kubernetes-patch-merge-key": "uid", + "x-kubernetes-patch-strategy": "merge", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "List of objects depended by this object. If ALL objects in the list have been deleted, this object will be garbage collected. If this object is managed by a controller, then an entry in this list will point to this controller, with the controller field set to true. There cannot be more than one managing controller.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.OwnerReference"), + }, + }, + }, + }, + }, + "finalizers": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "set", + "x-kubernetes-patch-strategy": "merge", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "Must be empty before the object is deleted from the registry. Each entry is an identifier for the responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entries in this list can only be removed. Finalizers may be processed and removed in any order. Order is NOT enforced because it introduces significant risk of stuck finalizers. finalizers is a shared field, any actor with permission can reorder it. If the finalizer list is processed in order, then this can lead to a situation in which the component responsible for the first finalizer in the list is waiting for a signal (field value, external system, or other) produced by a component responsible for a finalizer later in the list, resulting in a deadlock. Without enforced ordering finalizers are free to order amongst themselves and are not vulnerable to ordering changes in the list.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "managedFields": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "ManagedFields maps workflow-id and version to the set of fields that are managed by that workflow. This is mostly for internal housekeeping, and users typically shouldn't need to set or understand this field. A workflow can be the user's name, a controller's name, or the name of a specific apply path like \"ci-cd\". The set of fields is always in the version that the workflow used when modifying the object.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ManagedFieldsEntry"), + }, + }, + }, + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.ManagedFieldsEntry", "k8s.io/apimachinery/pkg/apis/meta/v1.OwnerReference", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, + } +} + +func schema_pkg_apis_meta_v1_OwnerReference(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "OwnerReference contains enough information to let you identify an owning object. An owning object must be in the same namespace as the dependent, or be cluster-scoped, so there is no namespace field.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "API version of the referent.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "uid": { + SchemaProps: spec.SchemaProps{ + Description: "UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "controller": { + SchemaProps: spec.SchemaProps{ + Description: "If true, this reference points to the managing controller.", + Type: []string{"boolean"}, + Format: "", + }, + }, + "blockOwnerDeletion": { + SchemaProps: spec.SchemaProps{ + Description: "If true, AND if the owner has the \"foregroundDeletion\" finalizer, then the owner cannot be deleted from the key-value store until this reference is removed. See https://kubernetes.io/docs/concepts/architecture/garbage-collection/#foreground-deletion for how the garbage collector interacts with this field and enforces the foreground deletion. Defaults to false. To set this field, a user needs \"delete\" permission of the owner, otherwise 422 (Unprocessable Entity) will be returned.", + Type: []string{"boolean"}, + Format: "", + }, + }, + }, + Required: []string{"apiVersion", "kind", "name", "uid"}, + }, + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-map-type": "atomic", + }, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_PartialObjectMetadata(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "PartialObjectMetadata is a generic representation of any object with ObjectMeta. It allows clients to get access to a particular ObjectMeta schema without knowing the details of the version.", + 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{ + Description: "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_pkg_apis_meta_v1_PartialObjectMetadataList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "PartialObjectMetadataList contains a list of objects containing only their metadata", + 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{ + Description: "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Description: "items contains each of the included items.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.PartialObjectMetadata"), + }, + }, + }, + }, + }, + }, + Required: []string{"items"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta", "k8s.io/apimachinery/pkg/apis/meta/v1.PartialObjectMetadata"}, + } +} + +func schema_pkg_apis_meta_v1_Patch(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Patch is provided to give a concrete name and type to the Kubernetes PATCH request body.", + Type: []string{"object"}, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_PatchOptions(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "PatchOptions may be provided when patching an API object. PatchOptions is meant to be a superset of UpdateOptions.", + 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: "", + }, + }, + "dryRun": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "force": { + SchemaProps: spec.SchemaProps{ + Description: "Force is going to \"force\" Apply requests. It means user will re-acquire conflicting fields owned by other people. Force flag must be unset for non-apply patch requests.", + Type: []string{"boolean"}, + Format: "", + }, + }, + "fieldManager": { + SchemaProps: spec.SchemaProps{ + Description: "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint. This field is required for apply requests (application/apply-patch) but optional for non-apply patch types (JsonPatch, MergePatch, StrategicMergePatch).", + Type: []string{"string"}, + Format: "", + }, + }, + "fieldValidation": { + SchemaProps: spec.SchemaProps{ + Description: "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default in v1.23+ - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_Preconditions(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "uid": { + SchemaProps: spec.SchemaProps{ + Description: "Specifies the target UID.", + Type: []string{"string"}, + Format: "", + }, + }, + "resourceVersion": { + SchemaProps: spec.SchemaProps{ + Description: "Specifies the target ResourceVersion", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_RootPaths(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "RootPaths lists the paths available at root. For example: \"/healthz\", \"/apis\".", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "paths": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "paths are the paths available at root.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + }, + Required: []string{"paths"}, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_ServerAddressByClientCIDR(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ServerAddressByClientCIDR helps the client to determine the server address that they should use, depending on the clientCIDR that they match.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "clientCIDR": { + SchemaProps: spec.SchemaProps{ + Description: "The CIDR with which clients can match their IP to figure out the server address that they should use.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "serverAddress": { + SchemaProps: spec.SchemaProps{ + Description: "Address of this server, suitable for a client that matches the above CIDR. This can be a hostname, hostname:port, IP or IP:port.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"clientCIDR", "serverAddress"}, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_Status(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Status is a return value for calls that don't return other objects.", + 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{ + Description: "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Description: "Status of the operation. One of: \"Success\" or \"Failure\". More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status", + Type: []string{"string"}, + Format: "", + }, + }, + "message": { + SchemaProps: spec.SchemaProps{ + Description: "A human-readable description of the status of this operation.", + Type: []string{"string"}, + Format: "", + }, + }, + "reason": { + SchemaProps: spec.SchemaProps{ + Description: "A machine-readable description of why this operation is in the \"Failure\" status. If this value is empty there is no information available. A Reason clarifies an HTTP status code but does not override it.", + Type: []string{"string"}, + Format: "", + }, + }, + "details": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "Extended data associated with the reason. Each reason may define its own extended details. This field is optional and the data returned is not guaranteed to conform to any schema except that defined by the reason type.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.StatusDetails"), + }, + }, + "code": { + SchemaProps: spec.SchemaProps{ + Description: "Suggested HTTP return code for this status, 0 if not set.", + Type: []string{"integer"}, + Format: "int32", + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta", "k8s.io/apimachinery/pkg/apis/meta/v1.StatusDetails"}, + } +} + +func schema_pkg_apis_meta_v1_StatusCause(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "StatusCause provides more information about an api.Status failure, including cases when multiple errors are encountered.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "reason": { + SchemaProps: spec.SchemaProps{ + Description: "A machine-readable description of the cause of the error. If this value is empty there is no information available.", + Type: []string{"string"}, + Format: "", + }, + }, + "message": { + SchemaProps: spec.SchemaProps{ + Description: "A human-readable description of the cause of the error. This field may be presented as-is to a reader.", + Type: []string{"string"}, + Format: "", + }, + }, + "field": { + SchemaProps: spec.SchemaProps{ + Description: "The field of the resource that has caused this error, as named by its JSON serialization. May include dot and postfix notation for nested attributes. Arrays are zero-indexed. Fields may appear more than once in an array of causes due to fields having multiple errors. Optional.\n\nExamples:\n \"name\" - the field \"name\" on the current resource\n \"items[0].name\" - the field \"name\" on the first array entry in \"items\"", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_StatusDetails(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "StatusDetails is a set of additional properties that MAY be set by the server to provide additional information about a response. The Reason field of a Status object defines what attributes will be set. Clients must ignore fields that do not match the defined type of each attribute, and should assume that any attribute may be empty, invalid, or under defined.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Description: "The name attribute of the resource associated with the status StatusReason (when there is a single name which can be described).", + Type: []string{"string"}, + Format: "", + }, + }, + "group": { + SchemaProps: spec.SchemaProps{ + Description: "The group attribute of the resource associated with the status StatusReason.", + Type: []string{"string"}, + Format: "", + }, + }, + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "uid": { + SchemaProps: spec.SchemaProps{ + Description: "UID of the resource. (when there is a single resource which can be described). More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids", + Type: []string{"string"}, + Format: "", + }, + }, + "causes": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "The Causes array includes more details associated with the StatusReason failure. Not all StatusReasons may provide detailed causes.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.StatusCause"), + }, + }, + }, + }, + }, + "retryAfterSeconds": { + SchemaProps: spec.SchemaProps{ + Description: "If specified, the time in seconds before the operation should be retried. Some errors may indicate the client must take an alternate action - for those errors this field may indicate how long to wait before taking the alternate action.", + Type: []string{"integer"}, + Format: "int32", + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.StatusCause"}, + } +} + +func schema_pkg_apis_meta_v1_Table(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Table is a tabular representation of a set of API resources. The server transforms the object into a set of preferred columns for quickly reviewing the objects.", + 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{ + Description: "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "columnDefinitions": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "columnDefinitions describes each column in the returned items array. The number of cells per row will always match the number of column definitions.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.TableColumnDefinition"), + }, + }, + }, + }, + }, + "rows": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "rows is the list of items in the table.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.TableRow"), + }, + }, + }, + }, + }, + }, + Required: []string{"columnDefinitions", "rows"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta", "k8s.io/apimachinery/pkg/apis/meta/v1.TableColumnDefinition", "k8s.io/apimachinery/pkg/apis/meta/v1.TableRow"}, + } +} + +func schema_pkg_apis_meta_v1_TableColumnDefinition(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TableColumnDefinition contains information about a column returned in the Table.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Description: "name is a human readable name for the column.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "type": { + SchemaProps: spec.SchemaProps{ + Description: "type is an OpenAPI type definition for this column, such as number, integer, string, or array. See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "format": { + SchemaProps: spec.SchemaProps{ + Description: "format is an optional OpenAPI type modifier for this column. A format modifies the type and imposes additional rules, like date or time formatting for a string. The 'name' format is applied to the primary identifier column which has type 'string' to assist in clients identifying column is the resource name. See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "description": { + SchemaProps: spec.SchemaProps{ + Description: "description is a human readable description of this column.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "priority": { + SchemaProps: spec.SchemaProps{ + Description: "priority is an integer defining the relative importance of this column compared to others. Lower numbers are considered higher priority. Columns that may be omitted in limited space scenarios should be given a higher priority.", + Default: 0, + Type: []string{"integer"}, + Format: "int32", + }, + }, + }, + Required: []string{"name", "type", "format", "description", "priority"}, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_TableOptions(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TableOptions are used when a Table is requested by the caller.", + 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: "", + }, + }, + "includeObject": { + SchemaProps: spec.SchemaProps{ + Description: "includeObject decides whether to include each object along with its columnar information. Specifying \"None\" will return no object, specifying \"Object\" will return the full object contents, and specifying \"Metadata\" (the default) will return the object's metadata in the PartialObjectMetadata kind in version v1beta1 of the meta.k8s.io API group.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_TableRow(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TableRow is an individual row in a table.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "cells": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "cells will be as wide as the column definitions array and may contain strings, numbers (float64 or int64), booleans, simple maps, lists, or null. See the type field of the column definition for a more detailed description.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Format: "", + }, + }, + }, + }, + }, + "conditions": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "conditions describe additional status of a row that are relevant for a human user. These conditions apply to the row, not to the object, and will be specific to table output. The only defined condition type is 'Completed', for a row that indicates a resource that has run to completion and can be given less visual priority.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.TableRowCondition"), + }, + }, + }, + }, + }, + "object": { + SchemaProps: spec.SchemaProps{ + Description: "This field contains the requested additional information about each object based on the includeObject policy when requesting the Table. If \"None\", this field is empty, if \"Object\" this will be the default serialization of the object for the current API version, and if \"Metadata\" (the default) will contain the object metadata. Check the returned kind and apiVersion of the object before parsing. The media type of the object will always match the enclosing list - if this as a JSON table, these will be JSON encoded objects.", + Ref: ref("k8s.io/apimachinery/pkg/runtime.RawExtension"), + }, + }, + }, + Required: []string{"cells"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.TableRowCondition", "k8s.io/apimachinery/pkg/runtime.RawExtension"}, + } +} + +func schema_pkg_apis_meta_v1_TableRowCondition(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TableRowCondition allows a row to be marked with additional information.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "type": { + SchemaProps: spec.SchemaProps{ + Description: "Type of row condition. The only defined value is 'Completed' indicating that the object this row represents has reached a completed state and may be given less visual priority than other rows. Clients are not required to honor any conditions but should be consistent where possible about handling the conditions.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Description: "Status of the condition, one of True, False, Unknown.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "reason": { + SchemaProps: spec.SchemaProps{ + Description: "(brief) machine readable reason for the condition's last transition.", + Type: []string{"string"}, + Format: "", + }, + }, + "message": { + SchemaProps: spec.SchemaProps{ + Description: "Human readable message indicating details about last transition.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"type", "status"}, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_Time(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Time is a wrapper around time.Time which supports correct marshaling to YAML and JSON. Wrappers are provided for many of the factory methods that the time package offers.", + Type: v1.Time{}.OpenAPISchemaType(), + Format: v1.Time{}.OpenAPISchemaFormat(), + }, + }, + } +} + +func schema_pkg_apis_meta_v1_Timestamp(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Timestamp is a struct that is equivalent to Time, but intended for protobuf marshalling/unmarshalling. It is generated into a serialization that matches Time. Do not use in Go structs.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "seconds": { + SchemaProps: spec.SchemaProps{ + Description: "Represents seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive.", + Default: 0, + Type: []string{"integer"}, + Format: "int64", + }, + }, + "nanos": { + SchemaProps: spec.SchemaProps{ + Description: "Non-negative fractions of a second at nanosecond resolution. Negative second values with fractions must still have non-negative nanos values that count forward in time. Must be from 0 to 999,999,999 inclusive. This field may be limited in precision depending on context.", + Default: 0, + Type: []string{"integer"}, + Format: "int32", + }, + }, + }, + Required: []string{"seconds", "nanos"}, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_TypeMeta(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TypeMeta describes an individual object in an API response or request with strings representing the type of the object and its API schema version. Structures that are versioned or persisted should inline TypeMeta.", + 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: "", + }, + }, + }, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_UpdateOptions(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "UpdateOptions may be provided when updating an API object. All fields in UpdateOptions should also be present in PatchOptions.", + 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: "", + }, + }, + "dryRun": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "fieldManager": { + SchemaProps: spec.SchemaProps{ + Description: "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.", + Type: []string{"string"}, + Format: "", + }, + }, + "fieldValidation": { + SchemaProps: spec.SchemaProps{ + Description: "fieldValidation instructs the server on how to handle objects in the request (POST/PUT/PATCH) containing unknown or duplicate fields. Valid values are: - Ignore: This will ignore any unknown fields that are silently dropped from the object, and will ignore all but the last duplicate field that the decoder encounters. This is the default behavior prior to v1.23. - Warn: This will send a warning via the standard warning response header for each unknown field that is dropped from the object, and for each duplicate field that is encountered. The request will still succeed if there are no other errors, and will only persist the last of any duplicate fields. This is the default in v1.23+ - Strict: This will fail the request with a BadRequest error if any unknown fields would be dropped from the object, or if any duplicate fields are present. The error returned from the server will contain all unknown and duplicate fields encountered.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + } +} + +func schema_pkg_apis_meta_v1_WatchEvent(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Event represents a single event to a watched resource.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "type": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "object": { + SchemaProps: spec.SchemaProps{ + Description: "Object is:\n * If Type is Added or Modified: the new state of the object.\n * If Type is Deleted: the state of the object immediately before deletion.\n * If Type is Error: *Status is recommended; other types may make sense\n depending on context.", + Ref: ref("k8s.io/apimachinery/pkg/runtime.RawExtension"), + }, + }, + }, + Required: []string{"type", "object"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/runtime.RawExtension"}, + } +} + +func schema_k8sio_apimachinery_pkg_runtime_RawExtension(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "RawExtension is used to hold extensions in external versions.\n\nTo use this, make a field which has RawExtension as its type in your external, versioned struct, and Object in your internal struct. You also need to register your various plugin types.\n\n// Internal package:\n\n\ttype MyAPIObject struct {\n\t\truntime.TypeMeta `json:\",inline\"`\n\t\tMyPlugin runtime.Object `json:\"myPlugin\"`\n\t}\n\n\ttype PluginA struct {\n\t\tAOption string `json:\"aOption\"`\n\t}\n\n// External package:\n\n\ttype MyAPIObject struct {\n\t\truntime.TypeMeta `json:\",inline\"`\n\t\tMyPlugin runtime.RawExtension `json:\"myPlugin\"`\n\t}\n\n\ttype PluginA struct {\n\t\tAOption string `json:\"aOption\"`\n\t}\n\n// On the wire, the JSON will look something like this:\n\n\t{\n\t\t\"kind\":\"MyAPIObject\",\n\t\t\"apiVersion\":\"v1\",\n\t\t\"myPlugin\": {\n\t\t\t\"kind\":\"PluginA\",\n\t\t\t\"aOption\":\"foo\",\n\t\t},\n\t}\n\nSo what happens? Decode first uses json or yaml to unmarshal the serialized data into your external MyAPIObject. That causes the raw JSON to be stored, but not unpacked. The next step is to copy (using pkg/conversion) into the internal struct. The runtime package's DefaultScheme has conversion functions installed which will unpack the JSON stored in RawExtension, turning it into the correct object type, and storing it in the Object. (TODO: In the case where the object is of an unknown type, a runtime.Unknown object will be created and stored.)", + Type: []string{"object"}, + }, + }, + } +} + +func schema_k8sio_apimachinery_pkg_runtime_TypeMeta(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TypeMeta is shared by all top level objects. The proper way to use it is to inline it in your type, like this:\n\n\ttype MyAwesomeAPIObject struct {\n\t runtime.TypeMeta `json:\",inline\"`\n\t ... // other fields\n\t}\n\nfunc (obj *MyAwesomeAPIObject) SetGroupVersionKind(gvk *metav1.GroupVersionKind) { metav1.UpdateTypeMeta(obj,gvk) }; GroupVersionKind() *GroupVersionKind\n\nTypeMeta is provided here for convenience. You may use it directly from this package or define your own with the same fields.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "kind": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + } +} + +func schema_k8sio_apimachinery_pkg_runtime_Unknown(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Unknown allows api objects with unknown types to be passed-through. This can be used to deal with the API objects from a plug-in. Unknown objects still have functioning TypeMeta features-- kind, version, etc. metadata and field mutatation.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "kind": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "ContentEncoding": { + SchemaProps: spec.SchemaProps{ + Description: "ContentEncoding is encoding used to encode 'Raw' data. Unspecified means no encoding.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "ContentType": { + SchemaProps: spec.SchemaProps{ + Description: "ContentType is serialization method used to serialize 'Raw'. Unspecified means ContentTypeJSON.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"ContentEncoding", "ContentType"}, + }, + }, + } +} + +func schema_k8sio_apimachinery_pkg_version_Info(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Info contains versioning information. how we'll want to distribute that information.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "major": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "minor": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "gitVersion": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "gitCommit": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "gitTreeState": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "buildDate": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "goVersion": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "compiler": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "platform": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"major", "minor", "gitVersion", "gitCommit", "gitTreeState", "buildDate", "goVersion", "compiler", "platform"}, + }, + }, + } +} diff --git a/contrib/mounts-virtualworkspace/reconciler/controllers.go b/contrib/mounts-virtualworkspace/reconciler/controllers.go new file mode 100644 index 00000000000..8e82a14fc02 --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/controllers.go @@ -0,0 +1,230 @@ +/* +Copyright 2023 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 reconciler + +import ( + "context" + + kcpdynamic "github.com/kcp-dev/client-go/dynamic" + kcpkubernetesclientset "github.com/kcp-dev/client-go/kubernetes" + kcpclusterclientset "github.com/kcp-dev/kcp/sdk/client/clientset/versioned/cluster" + + "k8s.io/client-go/rest" + "k8s.io/klog/v2" + + mountsclientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster" + mountskubecluster "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/reconciler/mounts/kubecluster" + mountsvcluster "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster" + targetskubecluster "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/reconciler/targets/kubecluster" + targetsvcluster "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/reconciler/targets/vcluster" +) + +func (s *shardManager) installTargetKubeClustersController(ctx context.Context) error { + logger := klog.FromContext(ctx).WithValues("shard", s.name, "controller", targetskubecluster.ControllerName) + + config := rest.CopyConfig(&s.shardClientConfig) + config = rest.AddUserAgent(config, targetskubecluster.ControllerName) + kcpClusterClient, err := kcpclusterclientset.NewForConfig(config) + if err != nil { + return err + } + + mountsClusterClient, err := mountsclientset.NewForConfig(config) + if err != nil { + return err + } + + kubeClusterClient, err := kcpkubernetesclientset.NewForConfig(config) + if err != nil { + return err + } + + dynamicClusterClient, err := kcpdynamic.NewForConfig(config) + if err != nil { + return err + } + + c, err := targetskubecluster.NewController( + kcpClusterClient, + mountsClusterClient, + kubeClusterClient, + dynamicClusterClient, + s.mountsSharedInformerFactory.Targets().V1alpha1().TargetKubeClusters(), + s.store, + s.virtualWorkspaceURL, + ) + if err != nil { + return err + } + + go func() { + // Wait for shared informer factories to by synced. + <-s.syncedCh + ctx = klog.NewContext(ctx, logger) + logger.Info("starting controller") + c.Start(ctx, 2) + }() + + return nil +} + +func (s *shardManager) installTargetVClustersController(ctx context.Context) error { + logger := klog.FromContext(ctx).WithValues("shard", s.name, "controller", targetsvcluster.ControllerName) + + config := rest.CopyConfig(&s.shardClientConfig) + config = rest.AddUserAgent(config, targetsvcluster.ControllerName) + kcpClusterClient, err := kcpclusterclientset.NewForConfig(config) + if err != nil { + return err + } + + mountsClusterClient, err := mountsclientset.NewForConfig(config) + if err != nil { + return err + } + + kubeClusterClient, err := kcpkubernetesclientset.NewForConfig(config) + if err != nil { + return err + } + + dynamicClusterClient, err := kcpdynamic.NewForConfig(config) + if err != nil { + return err + } + + c, err := targetsvcluster.NewController( + kcpClusterClient, + mountsClusterClient, + kubeClusterClient, + dynamicClusterClient, + s.mountsSharedInformerFactory.Targets().V1alpha1().TargetVClusters(), + s.store, + s.virtualWorkspaceURL, + ) + if err != nil { + return err + } + + go func() { + // Wait for shared informer factories to by synced. + <-s.syncedCh + ctx = klog.NewContext(ctx, logger) + logger.Info("starting controller") + c.Start(ctx, 2) + }() + + return nil +} + +func (s *shardManager) installKubeClusterMountsController(ctx context.Context) error { + logger := klog.FromContext(ctx).WithValues("shard", s.name, "controller", mountskubecluster.ControllerName) + + config := rest.CopyConfig(&s.shardClientConfig) + config = rest.AddUserAgent(config, mountskubecluster.ControllerName) + kcpClusterClient, err := kcpclusterclientset.NewForConfig(config) + if err != nil { + return err + } + + mountsClusterClient, err := mountsclientset.NewForConfig(config) + if err != nil { + return err + } + + kubeClusterClient, err := kcpkubernetesclientset.NewForConfig(config) + if err != nil { + return err + } + + dynamicClusterClient, err := kcpdynamic.NewForConfig(config) + if err != nil { + return err + } + + c, err := mountskubecluster.NewController( + kcpClusterClient, + mountsClusterClient, + kubeClusterClient, + dynamicClusterClient, + s.mountsSharedInformerFactory.Mounts().V1alpha1().KubeClusters(), + s.store, + s.virtualWorkspaceURL, + ) + if err != nil { + return err + } + + go func() { + // Wait for shared informer factories to by synced. + <-s.syncedCh + ctx = klog.NewContext(ctx, logger) + logger.Info("starting controller") + c.Start(ctx, 2) + }() + + return nil +} + +func (s *shardManager) installVClusterMountsController(ctx context.Context) error { + logger := klog.FromContext(ctx).WithValues("shard", s.name, "controller", mountsvcluster.ControllerName) + + config := rest.CopyConfig(&s.shardClientConfig) + config = rest.AddUserAgent(config, mountsvcluster.ControllerName) + kcpClusterClient, err := kcpclusterclientset.NewForConfig(config) + if err != nil { + return err + } + + mountsClusterClient, err := mountsclientset.NewForConfig(config) + if err != nil { + return err + } + + kubeClusterClient, err := kcpkubernetesclientset.NewForConfig(config) + if err != nil { + return err + } + + dynamicClusterClient, err := kcpdynamic.NewForConfig(config) + if err != nil { + return err + } + + c, err := mountsvcluster.NewController( + kcpClusterClient, + mountsClusterClient, + kubeClusterClient, + dynamicClusterClient, + s.mountsSharedInformerFactory.Mounts().V1alpha1().VClusters(), + s.store, + s.virtualWorkspaceURL, + ) + if err != nil { + return err + } + + go func() { + // Wait for shared informer factories to by synced. + <-s.syncedCh + ctx = klog.NewContext(ctx, logger) + logger.Info("starting controller") + c.Start(ctx, 2) + }() + + return nil +} diff --git a/contrib/mounts-virtualworkspace/reconciler/manager.go b/contrib/mounts-virtualworkspace/reconciler/manager.go new file mode 100644 index 00000000000..b64b32520e4 --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/manager.go @@ -0,0 +1,266 @@ +/* +Copyright 2023 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 reconciler + +import ( + "context" + "fmt" + "net/url" + "strings" + "time" + + "github.com/davecgh/go-spew/spew" + apisv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/apis/v1alpha1" + kcpclusterclientset "github.com/kcp-dev/kcp/sdk/client/clientset/versioned/cluster" + "github.com/kcp-dev/logicalcluster/v3" + "golang.org/x/sync/errgroup" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/rest" + "k8s.io/klog/v2" + + mountsclusterclientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster" + mountsinformers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" +) + +/* +The manager is in charge of instantiating and starting the controllers +that do the reconciliation for Mounts . +*/ + +const ( + targetsAPIExportName = "targets.contrib.kcp.io" + mountsAPIExportName = "mounts.contrib.kcp.io" + providersClusterPath = "root:providers:mounts" + + resyncPeriod = 10 * time.Hour +) + +// ShardManager is the interface for the manager for a shard +type shardManager struct { + name string + shardClientConfig rest.Config + virtualWorkspaceURL string + + store state.ClientSetStoreInterface + + mountsSharedInformerFactory mountsinformers.SharedInformerFactory + + stopCh chan struct{} + syncedCh chan struct{} +} + +type Manager struct { + // root:providers:mounts:targets.contrib.kcp.io + mountsTargetsExportShards map[string]shardManager + + // root:providers:mounts:mounts.contrib.kcp.io + mountsMountsExportShards map[string]shardManager +} + +// NewManager creates a manager able to start controllers +func NewManager(ctx context.Context, virtualWorkspaceURL string, kcpAdminRestConfig *rest.Config, store state.ClientSetStoreInterface) (*Manager, error) { + logger := klog.FromContext(ctx) + m := &Manager{ + mountsTargetsExportShards: map[string]shardManager{}, + mountsMountsExportShards: map[string]shardManager{}, + } + + logger.Info("setting up targets manager") + restClients, err := restConfigForAPIExport(ctx, kcpAdminRestConfig, targetsAPIExportName, logicalcluster.NewPath(providersClusterPath)) + if err != nil { + return nil, err + } + targetsShards, err := setupShardManager(ctx, virtualWorkspaceURL, restClients, store) + if err != nil { + return nil, err + } + + m.mountsTargetsExportShards = targetsShards + + logger.Info("setting up mounts manager") + restClients, err = restConfigForAPIExport(ctx, kcpAdminRestConfig, mountsAPIExportName, logicalcluster.NewPath(providersClusterPath)) + if err != nil { + return nil, err + } + mountsShards, err := setupShardManager(ctx, virtualWorkspaceURL, restClients, store) + if err != nil { + return nil, err + } + m.mountsMountsExportShards = mountsShards + + return m, nil + +} + +func setupShardManager(ctx context.Context, virtualWorkspaceURL string, clients []rest.Config, store state.ClientSetStoreInterface) (map[string]shardManager, error) { + logger := klog.FromContext(ctx) + logger.Info("shards found", "count", len(clients)) + shards := make(map[string]shardManager, len(clients)) + for _, c := range clients { + name := strings.Split(strings.TrimPrefix(c.Host, "https://"), ".")[0] + logger.Info("Shard", "name", name, "host", c.Host) + + informerMountsClient, err := mountsclusterclientset.NewForConfig(&c) + if err != nil { + return nil, err + } + + mountsSharedInformerFactory := mountsinformers.NewSharedInformerFactoryWithOptions( + informerMountsClient, + resyncPeriod, + ) + + s := shardManager{ + name: name, + virtualWorkspaceURL: virtualWorkspaceURL, + shardClientConfig: c, + store: store, + stopCh: make(chan struct{}), + syncedCh: make(chan struct{}), + mountsSharedInformerFactory: mountsSharedInformerFactory, + } + + shards[s.name] = s + } + + return shards, nil +} + +// Start starts informers and controller instances +func (m Manager) Start(ctx context.Context) error { + logger := klog.FromContext(ctx) + + logger.V(2).Info("starting manager") + + // HACK: tenancy controller is needed only on the start where tenancy workspace is + // scheduled. + g := errgroup.Group{} + + for _, s := range m.mountsTargetsExportShards { + ss := s + g.Go(func() error { + if err := ss.installTargetKubeClustersController(ctx); err != nil { + return err + } + if err := ss.installTargetVClustersController(ctx); err != nil { + return err + } + err := ss.start(ctx, "targets") + if err != nil { + return err + } + return nil + }) + } + + for _, s := range m.mountsMountsExportShards { + ss := s + g.Go(func() error { + if err := ss.installKubeClusterMountsController(ctx); err != nil { + return err + } + if err := ss.installVClusterMountsController(ctx); err != nil { + return err + } + err := ss.start(ctx, "mounts") + if err != nil { + return err + } + return nil + }) + } + + return g.Wait() +} + +func (s *shardManager) start(ctx context.Context, export string) error { + logger := klog.FromContext(ctx).WithValues("shard", s.name, "export", export) + + s.mountsSharedInformerFactory.Start(s.stopCh) + + logger.Info("waiting for targets informers sync") + wg := errgroup.Group{} + wg.Go(func() error { + s.mountsSharedInformerFactory.WaitForCacheSync(s.stopCh) + return nil + }) + wg.Wait() + + logger.Info("all informers synced, ready to start controllers") + close(s.syncedCh) + return nil +} + +// restConfigForAPIExport returns a *rest.Config properly configured to communicate with the endpoint for the +// APIExport's virtual workspace. cfg is the bootstrap config, shardsClientConfig is the config for the shards clusters. +func restConfigForAPIExport(ctx context.Context, kcpAdminRestConfig *rest.Config, apiExportName string, cluster logicalcluster.Path) ([]rest.Config, error) { + logger := klog.FromContext(ctx) + logger.V(2).Info("getting apiexport") + + bootstrapConfig := rest.CopyConfig(kcpAdminRestConfig) + h, err := url.Parse(bootstrapConfig.Host) + if err != nil { + return nil, err + } + h.Path = "" + bootstrapConfig.Host = h.String() + bootstrapClient, err := kcpclusterclientset.NewForConfig(bootstrapConfig) + if err != nil { + return nil, err + } + spew.Dump(cluster) + spew.Dump(bootstrapClient.Cluster(cluster).ApisV1alpha1().APIConversions().List(ctx, metav1.ListOptions{})) + + var apiExport *apisv1alpha1.APIExport + if apiExportName != "" { + if apiExport, err = bootstrapClient.ApisV1alpha1().APIExports().Cluster(cluster).Get(ctx, apiExportName, metav1.GetOptions{}); err != nil { + return nil, fmt.Errorf("error getting APIExport %q: %w", apiExportName, err) + } + } else { + logger := klog.FromContext(ctx) + logger.V(2).Info("api-export-name is empty - listing") + exports := &apisv1alpha1.APIExportList{} + if exports, err = bootstrapClient.ApisV1alpha1().APIExports().List(ctx, metav1.ListOptions{}); err != nil { + return nil, fmt.Errorf("error listing APIExports: %w", err) + } + if len(exports.Items) == 0 { + return nil, fmt.Errorf("no APIExport found") + } + if len(exports.Items) > 1 { + return nil, fmt.Errorf("more than one APIExport found") + } + apiExport = &exports.Items[0] + } + + if len(apiExport.Status.VirtualWorkspaces) < 1 { + return nil, fmt.Errorf("APIExport %q status.virtualWorkspaces is empty", apiExportName) + } + + var results []rest.Config + // TODO(mjudeikis): This should use separate rest.Config for direct shard communication. + // KCPAdmin pointing to frontproxy would not works. This works only with `kcp start` + for _, ws := range apiExport.Status.VirtualWorkspaces { + logger.Info("virtual workspace", "url", ws.URL) + cfg := rest.CopyConfig(kcpAdminRestConfig) + cfg.Host = ws.URL + results = append(results, *cfg) + } + + return results, nil +} diff --git a/contrib/mounts-virtualworkspace/reconciler/mounts/README.md b/contrib/mounts-virtualworkspace/reconciler/mounts/README.md new file mode 100644 index 00000000000..d2730afcee4 --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/mounts/README.md @@ -0,0 +1,14 @@ +# Mounts reconciler + +Mounts reconciles the mount in the specific workspace and does the following: + +- for now if it find secret in store - sets it ready + + +## VCluster controller + +Order and flow: +1. `Finalizer` and sets finaziler and stop & requeue if change was done. (metadata change) +2. `Delegated/Direct` and sets `mountsv1alpha1.ClusterSecretReady,` (status change) and passthrough. +3. `Provisioner` and sets `mountsv1alpha1.ClusterReady,` (status change) and passthrough. +4. `Deprovisioner` and sets `mountsv1alpha1.ClusterNotReady,` (status change) and passthrough. diff --git a/contrib/mounts-virtualworkspace/reconciler/mounts/kubecluster/mounts_controller.go b/contrib/mounts-virtualworkspace/reconciler/mounts/kubecluster/mounts_controller.go new file mode 100644 index 00000000000..8e73020a5d8 --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/mounts/kubecluster/mounts_controller.go @@ -0,0 +1,208 @@ +/* +Copyright 2024 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 kubecluster + +import ( + "context" + "fmt" + "time" + + kcpcache "github.com/kcp-dev/apimachinery/v2/pkg/cache" + kcpdynamic "github.com/kcp-dev/client-go/dynamic" + kcpkubernetesclientset "github.com/kcp-dev/client-go/kubernetes" + "github.com/kcp-dev/kcp/pkg/informer" + "github.com/kcp-dev/kcp/pkg/logging" + "github.com/kcp-dev/kcp/pkg/reconciler/committer" + kcpclientset "github.com/kcp-dev/kcp/sdk/client/clientset/versioned/cluster" + + kerrors "k8s.io/apimachinery/pkg/api/errors" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog/v2" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + mountsclientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster" + mountsv1alpha1client "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1" + mountsv1alpha1informers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions/mounts/v1alpha1" + mountsv1alpha1listers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/listers/mounts/v1alpha1" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" +) + +const ( + // ControllerName is the name of this controller. + ControllerName = "kcp-mounts-kubeclusters" +) + +// NewController creates a new controller for targets. +func NewController( + kcpClusterClient kcpclientset.ClusterInterface, + mountsClusterClient mountsclientset.ClusterInterface, + kubeClusterClient kcpkubernetesclientset.ClusterInterface, + dynamicClusterClient kcpdynamic.ClusterInterface, + mountsInformers mountsv1alpha1informers.KubeClusterClusterInformer, + store state.ClientSetStoreInterface, + virtualWorkspaceURL string, +) (*Controller, error) { + c := &Controller{ + queue: workqueue.NewTypedRateLimitingQueueWithConfig( + workqueue.DefaultTypedControllerRateLimiter[string](), + workqueue.TypedRateLimitingQueueConfig[string]{ + Name: ControllerName, + }, + ), + + store: store, + + dynamicClusterClient: dynamicClusterClient, + kubeClusterClient: kubeClusterClient, + + mountsIndexer: mountsInformers.Informer().GetIndexer(), + mountsLister: mountsInformers.Lister(), + + commit: committer.NewCommitter[*mountsv1alpha1.KubeCluster, mountsv1alpha1client.KubeClusterInterface, *mountsv1alpha1.KubeClusterSpec, *mountsv1alpha1.KubeClusterStatus](mountsClusterClient.MountsV1alpha1().KubeClusters()), + } + + _, _ = mountsInformers.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { c.enqueue(obj) }, + UpdateFunc: func(_, obj interface{}) { c.enqueue(obj) }, + }) + + return c, nil +} + +type mountResources = committer.Resource[*mountsv1alpha1.KubeClusterSpec, *mountsv1alpha1.KubeClusterStatus] + +// Controller watches Targets and dynamically discovered mount resources and reconciles them so +// workspace has right annotations. +type Controller struct { + // queue is the work-queue used by the controller + queue workqueue.TypedRateLimitingInterface[string] + store state.ClientSetStoreInterface + virtualWorkspaceURL string + + dynamicClusterClient kcpdynamic.ClusterInterface + kubeClusterClient kcpkubernetesclientset.ClusterInterface + + discoveringDynamicSharedInformerFactory *informer.DiscoveringDynamicSharedInformerFactory + + mountsIndexer cache.Indexer + mountsLister mountsv1alpha1listers.KubeClusterClusterLister + + // commit creates a patch and submits it, if needed. + commit func(ctx context.Context, new, old *mountResources) error +} + +// enqueue adds the object to the work queue. +func (c *Controller) enqueue(obj interface{}) { + key, err := kcpcache.MetaClusterNamespaceKeyFunc(obj) + if err != nil { + runtime.HandleError(err) + return + } + logger := logging.WithQueueKey(logging.WithReconciler(klog.Background(), ControllerName), key) + logger.V(4).Info("queueing KubeCluster mount") + c.queue.Add(key) +} + +func (c *Controller) Start(ctx context.Context, numThreads int) { + defer runtime.HandleCrash() + defer c.queue.ShutDown() + + logger := logging.WithReconciler(klog.FromContext(ctx), ControllerName) + ctx = klog.NewContext(ctx, logger) + logger.Info("Starting controller") + defer logger.Info("Shutting down controller") + + for i := 0; i < numThreads; i++ { + go wait.Until(func() { c.startWorker(ctx) }, time.Second, ctx.Done()) + } + + <-ctx.Done() +} + +func (c *Controller) startWorker(ctx context.Context) { + for c.processNextWorkItem(ctx) { + } +} + +func (c *Controller) processNextWorkItem(ctx context.Context) bool { + // Wait until there is a new item in the working queue + k, quit := c.queue.Get() + if quit { + return false + } + key := k + + logger := logging.WithQueueKey(klog.FromContext(ctx), key) + ctx = klog.NewContext(ctx, logger) + logger.V(4).Info("processing key") + + // No matter what, tell the queue we're done with this key, to unblock + // other workers. + defer c.queue.Done(key) + + if requeue, err := c.process(ctx, key); err != nil { + runtime.HandleError(fmt.Errorf("%q controller failed to sync %q, err: %w", ControllerName, key, err)) + c.queue.AddRateLimited(key) + return true + } else if requeue { + // only requeue if we didn't error, but we still want to requeue + c.queue.Add(key) + return true + } + c.queue.Forget(key) + return true +} + +func (c *Controller) process(ctx context.Context, key string) (bool, error) { + parent, _, name, err := kcpcache.SplitMetaClusterNamespaceKey(key) + if err != nil { + return false, err + } + + mount, err := c.mountsLister.Cluster(parent).Get(name) + if err != nil { + if kerrors.IsNotFound(err) { + return false, nil // object deleted before we handled it + } + return false, err + } + + old := mount + mount = mount.DeepCopy() + + logger := logging.WithObject(klog.FromContext(ctx), mount) + ctx = klog.NewContext(ctx, logger) + + var errs []error + requeue, err := c.reconcile(ctx, mount) + if err != nil { + errs = append(errs, err) + } + + // If the object being reconciled changed as a result, update it. + oldResource := &mountResources{ObjectMeta: old.ObjectMeta, Spec: &old.Spec, Status: &old.Status} + newResource := &mountResources{ObjectMeta: mount.ObjectMeta, Spec: &mount.Spec, Status: &mount.Status} + if err := c.commit(ctx, oldResource, newResource); err != nil { + errs = append(errs, err) + } + + return requeue, utilerrors.NewAggregate(errs) +} diff --git a/contrib/mounts-virtualworkspace/reconciler/mounts/kubecluster/mounts_reconcile.go b/contrib/mounts-virtualworkspace/reconciler/mounts/kubecluster/mounts_reconcile.go new file mode 100644 index 00000000000..b9fc5dd9191 --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/mounts/kubecluster/mounts_reconcile.go @@ -0,0 +1,104 @@ +/* +Copyright 2024 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 kubecluster + +import ( + "context" + "net/url" + "time" + + "github.com/kcp-dev/logicalcluster/v3" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilserrors "k8s.io/apimachinery/pkg/util/errors" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" +) + +// TODO: This ended up same code as targetsKubeClusters. Need to rething data model for this +// as its a signal something is wrong. + +type reconcileStatus int + +const ( + reconcileStatusStopAndRequeue reconcileStatus = iota + reconcileAfterRequeue + reconcileStatusContinue +) + +type reconciler interface { + reconcile(ctx context.Context, mount *mountsv1alpha1.KubeCluster) (reconcileStatus, error) +} + +// reconcile reconciles the workspace objects. It is intended to be single reconciler for all the +// workspace replated operations. For now it has single reconciler that updates the status of the +// workspace based on the mount status. +func (c *Controller) reconcile(ctx context.Context, mount *mountsv1alpha1.KubeCluster) (bool, error) { + u, err := url.Parse(c.virtualWorkspaceURL) + if err != nil { + return false, err + } + reconcilers := []reconciler{ + &delegatedReconciler{ + getState: func(key string) (state.Value, bool) { + return c.store.Get(state.KindKubeClusters, key) + }}, + &directReconciler{ + getSecret: func(ctx context.Context, cluster logicalcluster.Path, namespaces, name string) (*corev1.Secret, error) { + return c.kubeClusterClient.CoreV1().Cluster(cluster).Secrets(namespaces).Get(ctx, name, metav1.GetOptions{}) + }, + getState: func(key string) (state.Value, bool) { + return c.store.Get(state.KindKubeClusters, key) + }, + setState: func(key string, value state.Value) { + c.store.Set(state.KindKubeClusters, key, value) + }, + deleteState: func(key string) { + c.store.Delete(state.KindKubeClusters, key) + }, + getVirtualWorkspaceURL: func() *url.URL { + return u + }, + }, + } + + var errs []error + + requeue := false + for _, r := range reconcilers { + var err error + var status reconcileStatus + status, err = r.reconcile(ctx, mount) + if err != nil { + errs = append(errs, err) + } + if status == reconcileStatusStopAndRequeue { + requeue = true + break + } + if status == reconcileAfterRequeue { + requeue = true + // HACK: should be done in the queue. + time.Sleep(5 * time.Second) + break + } + } + + return requeue, utilserrors.NewAggregate(errs) +} diff --git a/contrib/mounts-virtualworkspace/reconciler/mounts/kubecluster/mounts_reconcile_delegated.go b/contrib/mounts-virtualworkspace/reconciler/mounts/kubecluster/mounts_reconcile_delegated.go new file mode 100644 index 00000000000..a8c3a743411 --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/mounts/kubecluster/mounts_reconcile_delegated.go @@ -0,0 +1,88 @@ +/* +Copyright 2024 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 kubecluster + +import ( + "context" + "net/url" + + tenancyv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/tenancy/v1alpha1" + conditionsapi "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/util/conditions" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" +) + +// delegatedReconciler is a reconciler reconciles mounts, which are delegated and +// has secrets string set. +type delegatedReconciler struct { + getState func(key string) (state.Value, bool) +} + +func (r *delegatedReconciler) reconcile(ctx context.Context, mount *mountsv1alpha1.KubeCluster) (reconcileStatus, error) { + if mount.Spec.Mode != mountsv1alpha1.KubeClusterModeDelegated { + return reconcileStatusContinue, nil + } + + if mount.Spec.SecretString == nil || *mount.Spec.SecretString == "" { + conditions.Set(mount, &conditionsapi.Condition{ + Type: tenancyv1alpha1.MountConditionReady, + Status: corev1.ConditionFalse, + Message: "SecretString is not set", + }) + } + + v, found := r.getState(*mount.Spec.SecretString) + if v.Client == nil || !found { + conditions.Set(mount, &conditionsapi.Condition{ + Type: tenancyv1alpha1.MountConditionReady, + Status: corev1.ConditionFalse, + Message: "Failed to get client. Most likely the secret is wrong.", + }) + return reconcileAfterRequeue, nil + } + + _, err := v.Client.CoreV1().Namespaces().List(ctx, metav1.ListOptions{}) + if err != nil { + conditions.Set(mount, &conditionsapi.Condition{ + Type: tenancyv1alpha1.MountConditionReady, + Status: corev1.ConditionFalse, + Message: "Failed to health check", + }) + return reconcileAfterRequeue, nil + } + + conditions.Set(mount, &conditionsapi.Condition{ + Type: tenancyv1alpha1.MountConditionReady, + Status: corev1.ConditionTrue, + }) + mount.Status.Phase = tenancyv1alpha1.MountPhaseReady + + // secrets string will be purged at VW side. + // TOOD: This is a temporary solution. We need to find a better way to handle this. + full, err := url.JoinPath(v.URL, "secret", *mount.Spec.SecretString) + if err != nil { + return reconcileStatusStopAndRequeue, err + } + mount.Status.URL = full + + return reconcileStatusContinue, nil +} diff --git a/contrib/mounts-virtualworkspace/reconciler/mounts/kubecluster/mounts_reconcile_direct.go b/contrib/mounts-virtualworkspace/reconciler/mounts/kubecluster/mounts_reconcile_direct.go new file mode 100644 index 00000000000..d9717665167 --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/mounts/kubecluster/mounts_reconcile_direct.go @@ -0,0 +1,151 @@ +/* +Copyright 2024 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 kubecluster + +import ( + "context" + "fmt" + "net/url" + "path" + + tenancyv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/tenancy/v1alpha1" + conditionsapi "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/util/conditions" + "github.com/kcp-dev/logicalcluster/v3" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/utils/clientgo" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/utils/secrets" +) + +const ( + proxyPrefix = "/services/cluster-proxy/" +) + +// directReconciler is a reconciler reconciles mounts, which are direct and +// has secret set. +type directReconciler struct { + getState func(key string) (state.Value, bool) + setState func(key string, value state.Value) + getSecret func(ctx context.Context, cluster logicalcluster.Path, namespace, name string) (*corev1.Secret, error) + deleteState func(key string) + getVirtualWorkspaceURL func() *url.URL +} + +func (r *directReconciler) reconcile(ctx context.Context, mount *mountsv1alpha1.KubeCluster) (reconcileStatus, error) { + if mount.Spec.Mode != mountsv1alpha1.KubeClusterModeDirect { + return reconcileStatusContinue, nil + } + + secretRef := mount.Spec.SecretRef + if secretRef == nil { + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterReady, + Status: corev1.ConditionFalse, + Message: "secretRef is not set", + }) + return reconcileStatusStopAndRequeue, nil + } + + cluster := logicalcluster.NewPath(logicalcluster.From(mount).String()) + + mount.Status.Phase = tenancyv1alpha1.MountPhaseConnecting + + // set secret first: + if mount.Status.SecretString == "" { + secretString, err := secrets.GenerateSecret(16) + if err != nil { + return reconcileStatusStopAndRequeue, err + } + mount.Status.SecretString = secretString + } + + secret, err := r.getSecret(ctx, cluster, secretRef.Namespace, secretRef.Name) + if err != nil { + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterReady, + Status: corev1.ConditionFalse, + Message: fmt.Sprintf("failed to get secret %s/%s: %v", secretRef.Namespace, secretRef.Name, err), + }) + r.deleteState(mount.Status.SecretString) + return reconcileStatusStopAndRequeue, err + } + + if secret.Data["kubeconfig"] == nil { + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterReady, + Status: corev1.ConditionFalse, + Message: fmt.Sprintf("secret %s/%s does not contain 'kubeconfig' key", secretRef.Namespace, secretRef.Name), + }) + r.deleteState(mount.Status.SecretString) + return reconcileStatusStopAndRequeue, nil + } + + clientset, rest, err := clientgo.GetClientFromKubeConfig(secret.Data["kubeconfig"]) + if err != nil { + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterReady, + Status: corev1.ConditionFalse, + Message: fmt.Sprintf("failed to create client from kubeconfig in secret %s/%s: %v", secretRef.Namespace, secretRef.Name, err), + }) + r.deleteState(mount.Status.SecretString) + return reconcileStatusStopAndRequeue, err + } + + _, err = clientset.CoreV1().Namespaces().List(ctx, metav1.ListOptions{}) + if err != nil { + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterReady, + Status: corev1.ConditionFalse, + Message: fmt.Sprintf("failed to access namespaces from kubeconfig in secret %s/%s: %v", secretRef.Namespace, secretRef.Name, err), + }) + r.deleteState(mount.Status.SecretString) + return reconcileStatusStopAndRequeue, err + } + + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterReady, + Status: corev1.ConditionTrue, + Message: fmt.Sprintf("successfully accessed namespaces from kubeconfig in secret %s/%s", secretRef.Namespace, secretRef.Name), + }) + + // construct url for mount: + kubeClusterVirtualWorkspaceURL := r.getVirtualWorkspaceURL() + kubeClusterVirtualWorkspaceURL.Path = path.Join( + proxyPrefix, + logicalcluster.From(mount).String(), + "apis", + mountsv1alpha1.SchemeGroupVersion.String(), + "kubeclusters", + mount.Name, + "proxy", + ) + mount.Status.URL = kubeClusterVirtualWorkspaceURL.String() + + r.setState(mount.Status.SecretString, state.Value{ + Client: clientset, + URL: mount.Status.URL, + Config: rest, + }) + mount.Status.Phase = tenancyv1alpha1.MountPhaseReady + + return reconcileStatusContinue, nil +} diff --git a/contrib/mounts-virtualworkspace/reconciler/mounts/utils.go b/contrib/mounts-virtualworkspace/reconciler/mounts/utils.go new file mode 100644 index 00000000000..b5d7cb8b62c --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/mounts/utils.go @@ -0,0 +1,39 @@ +package mounts + +import ( + "crypto/rand" + "encoding/base64" + "fmt" + + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" +) + +func getClientFromKubeConfig(kubeconfig []byte) (*kubernetes.Clientset, *rest.Config, error) { + config, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) + if err != nil { + return nil, nil, err + } + + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + return nil, nil, err + } + + return clientset, config, nil +} + +// generateSecret generates a random string of specified length +func generateSecret(length int) (string, error) { + // Allocate a byte slice for the random bytes + bytes := make([]byte, length) + + // Read random bytes into the slice + if _, err := rand.Read(bytes); err != nil { + return "", fmt.Errorf("failed to generate random bytes: %w", err) + } + + // Encode the bytes to a base64 string to make it printable + return base64.URLEncoding.EncodeToString(bytes)[:length], nil +} diff --git a/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_controller.go b/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_controller.go new file mode 100644 index 00000000000..f5efb13474f --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_controller.go @@ -0,0 +1,209 @@ +/* +Copyright 2024 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 vcluster + +import ( + "context" + "fmt" + "time" + + kcpcache "github.com/kcp-dev/apimachinery/v2/pkg/cache" + kcpdynamic "github.com/kcp-dev/client-go/dynamic" + kcpkubernetesclientset "github.com/kcp-dev/client-go/kubernetes" + "github.com/kcp-dev/kcp/pkg/informer" + "github.com/kcp-dev/kcp/pkg/logging" + "github.com/kcp-dev/kcp/pkg/reconciler/committer" + kcpclientset "github.com/kcp-dev/kcp/sdk/client/clientset/versioned/cluster" + + kerrors "k8s.io/apimachinery/pkg/api/errors" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog/v2" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + mountsclientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster" + mountsv1alpha1client "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/mounts/v1alpha1" + mountsv1alpha1informers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions/mounts/v1alpha1" + mountsv1alpha1listers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/listers/mounts/v1alpha1" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" +) + +const ( + // ControllerName is the name of this controller. + ControllerName = "kcp-mounts-vclusters" +) + +// NewController creates a new controller for targets. +func NewController( + kcpClusterClient kcpclientset.ClusterInterface, + mountsClusterClient mountsclientset.ClusterInterface, + kubeClusterClient kcpkubernetesclientset.ClusterInterface, + dynamicClusterClient kcpdynamic.ClusterInterface, + mountsInformers mountsv1alpha1informers.VClusterClusterInformer, + store state.ClientSetStoreInterface, + virtualWorkspaceURL string, +) (*Controller, error) { + c := &Controller{ + queue: workqueue.NewTypedRateLimitingQueueWithConfig( + workqueue.DefaultTypedControllerRateLimiter[string](), + workqueue.TypedRateLimitingQueueConfig[string]{ + Name: ControllerName, + }, + ), + + store: store, + + dynamicClusterClient: dynamicClusterClient, + kubeClusterClient: kubeClusterClient, + + mountsIndexer: mountsInformers.Informer().GetIndexer(), + mountsLister: mountsInformers.Lister(), + + commit: committer.NewCommitter[*mountsv1alpha1.VCluster, mountsv1alpha1client.VClusterInterface, *mountsv1alpha1.VClusterSpec, *mountsv1alpha1.VClusterStatus](mountsClusterClient.MountsV1alpha1().VClusters()), + } + + _, _ = mountsInformers.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { c.enqueue(obj) }, + UpdateFunc: func(_, obj interface{}) { c.enqueue(obj) }, + DeleteFunc: func(obj interface{}) { c.enqueue(obj) }, + }) + + return c, nil +} + +type mountResources = committer.Resource[*mountsv1alpha1.VClusterSpec, *mountsv1alpha1.VClusterStatus] + +// Controller watches Targets and dynamically discovered mount resources and reconciles them so +// workspace has right annotations. +type Controller struct { + // queue is the work-queue used by the controller + queue workqueue.TypedRateLimitingInterface[string] + store state.ClientSetStoreInterface + virtualWorkspaceURL string + + dynamicClusterClient kcpdynamic.ClusterInterface + kubeClusterClient kcpkubernetesclientset.ClusterInterface + + discoveringDynamicSharedInformerFactory *informer.DiscoveringDynamicSharedInformerFactory + + mountsIndexer cache.Indexer + mountsLister mountsv1alpha1listers.VClusterClusterLister + + // commit creates a patch and submits it, if needed. + commit func(ctx context.Context, new, old *mountResources) error +} + +// enqueue adds the object to the work queue. +func (c *Controller) enqueue(obj interface{}) { + key, err := kcpcache.MetaClusterNamespaceKeyFunc(obj) + if err != nil { + runtime.HandleError(err) + return + } + logger := logging.WithQueueKey(logging.WithReconciler(klog.Background(), ControllerName), key) + logger.V(4).Info("queueing VCluster mount") + c.queue.Add(key) +} + +func (c *Controller) Start(ctx context.Context, numThreads int) { + defer runtime.HandleCrash() + defer c.queue.ShutDown() + + logger := logging.WithReconciler(klog.FromContext(ctx), ControllerName) + ctx = klog.NewContext(ctx, logger) + logger.Info("Starting controller") + defer logger.Info("Shutting down controller") + + for i := 0; i < numThreads; i++ { + go wait.Until(func() { c.startWorker(ctx) }, time.Second, ctx.Done()) + } + + <-ctx.Done() +} + +func (c *Controller) startWorker(ctx context.Context) { + for c.processNextWorkItem(ctx) { + } +} + +func (c *Controller) processNextWorkItem(ctx context.Context) bool { + // Wait until there is a new item in the working queue + k, quit := c.queue.Get() + if quit { + return false + } + key := k + + logger := logging.WithQueueKey(klog.FromContext(ctx), key) + ctx = klog.NewContext(ctx, logger) + logger.V(4).Info("processing key") + + // No matter what, tell the queue we're done with this key, to unblock + // other workers. + defer c.queue.Done(key) + + if requeue, err := c.process(ctx, key); err != nil { + runtime.HandleError(fmt.Errorf("%q controller failed to sync %q, err: %w", ControllerName, key, err)) + c.queue.AddRateLimited(key) + return true + } else if requeue { + // only requeue if we didn't error, but we still want to requeue + c.queue.Add(key) + return true + } + c.queue.Forget(key) + return true +} + +func (c *Controller) process(ctx context.Context, key string) (bool, error) { + parent, _, name, err := kcpcache.SplitMetaClusterNamespaceKey(key) + if err != nil { + return false, err + } + + mount, err := c.mountsLister.Cluster(parent).Get(name) + if err != nil { + if kerrors.IsNotFound(err) { + return false, nil // object deleted before we handled it + } + return false, err + } + + old := mount + mount = mount.DeepCopy() + + logger := logging.WithObject(klog.FromContext(ctx), mount) + ctx = klog.NewContext(ctx, logger) + + var errs []error + requeue, err := c.reconcile(ctx, mount) + if err != nil { + errs = append(errs, err) + } + + // If the object being reconciled changed as a result, update it. + oldResource := &mountResources{ObjectMeta: old.ObjectMeta, Spec: &old.Spec, Status: &old.Status} + newResource := &mountResources{ObjectMeta: mount.ObjectMeta, Spec: &mount.Spec, Status: &mount.Status} + if err := c.commit(ctx, oldResource, newResource); err != nil { + errs = append(errs, err) + } + + return requeue, utilerrors.NewAggregate(errs) +} diff --git a/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_reconcile.go b/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_reconcile.go new file mode 100644 index 00000000000..465ba1b8f3a --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_reconcile.go @@ -0,0 +1,110 @@ +/* +Copyright 2024 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 vcluster + +import ( + "context" + "net/url" + + "github.com/kcp-dev/logicalcluster/v3" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilserrors "k8s.io/apimachinery/pkg/util/errors" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" +) + +// TODO: This ended up same code as targetsKubeClusters, kubeclusters. Need to rethink data model for this +// as its a signal something is wrong. + +type reconcileStatus int + +const ( + reconcileStatusStopAndRequeue reconcileStatus = iota + reconcileStatusContinue +) + +type reconciler interface { + reconcile(ctx context.Context, mount *mountsv1alpha1.VCluster) (reconcileStatus, error) +} + +// reconcile reconciles the workspace objects. It is intended to be single reconciler for all the +// workspace replated operations. For now it has single reconciler that updates the status of the +// workspace based on the mount status. +func (c *Controller) reconcile(ctx context.Context, mount *mountsv1alpha1.VCluster) (bool, error) { + u, err := url.Parse(c.virtualWorkspaceURL) + if err != nil { + return false, err + } + reconcilers := []reconciler{ + &finalizerReconciler{}, + &delegatedReconciler{ + getState: func(key string) (state.Value, bool) { + return c.store.Get(state.KindVClusters, key) + }}, + &directReconciler{ + getSecret: func(ctx context.Context, cluster logicalcluster.Path, namespaces, name string) (*corev1.Secret, error) { + return c.kubeClusterClient.CoreV1().Cluster(cluster).Secrets(namespaces).Get(ctx, name, metav1.GetOptions{}) + }, + getState: func(key string) (state.Value, bool) { + return c.store.Get(state.KindVClusters, key) + }, + setState: func(key string, value state.Value) { + c.store.Set(state.KindVClusters, key, value) + }, + deleteState: func(key string) { + c.store.Delete(state.KindVClusters, key) + }, + getVirtualWorkspaceURL: func() *url.URL { + return u + }, + }, + &provisionerReconciler{ + getState: func(key string) (state.Value, bool) { + return c.store.Get(state.KindVClusters, key) + }, + setState: func(key string, value state.Value) { + c.store.Set(state.KindVClusters, key, value) + }, + }, + &deprovisionerReconciler{ + getState: func(key string) (state.Value, bool) { + return c.store.Get(state.KindVClusters, key) + }, + }, + } + + var errs []error + + requeue := false + for _, r := range reconcilers { + var err error + var status reconcileStatus + status, err = r.reconcile(ctx, mount) + if err != nil { + errs = append(errs, err) + } + if status == reconcileStatusStopAndRequeue { + requeue = true + break + } + } + + return requeue, utilserrors.NewAggregate(errs) +} diff --git a/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_reconcile_delegated.go b/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_reconcile_delegated.go new file mode 100644 index 00000000000..e37dc123e08 --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_reconcile_delegated.go @@ -0,0 +1,80 @@ +/* +Copyright 2024 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 vcluster + +import ( + "context" + + tenancyv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/tenancy/v1alpha1" + conditionsapi "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/util/conditions" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" +) + +// delegatedReconciler is a reconciler reconciles mounts, which are delegated and +// has secrets string set. +// It is responsible for reconciling mounts with ClusterSecretReady condition. +type delegatedReconciler struct { + getState func(key string) (state.Value, bool) +} + +func (r *delegatedReconciler) reconcile(ctx context.Context, mount *mountsv1alpha1.VCluster) (reconcileStatus, error) { + if mount.Spec.Mode != mountsv1alpha1.KubeClusterModeDelegated { + return reconcileStatusContinue, nil + } + + mount.Status.Phase = tenancyv1alpha1.MountPhaseInitializing + if mount.Spec.SecretString == nil || *mount.Spec.SecretString == "" { + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterSecretReady, + Status: corev1.ConditionFalse, + Message: "SecretString is not set", + }) + return reconcileStatusStopAndRequeue, nil + } + + v, found := r.getState(*mount.Spec.SecretString) + if v.Client == nil || !found { + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterSecretReady, + Status: corev1.ConditionFalse, + Message: "Failed to get client. Most likely the secret is wrong.", + }) + return reconcileStatusStopAndRequeue, nil + } + + _, err := v.Client.CoreV1().Namespaces().List(ctx, metav1.ListOptions{}) + if err != nil { + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterSecretReady, + Status: corev1.ConditionFalse, + Message: "Failed to health check", + }) + return reconcileStatusStopAndRequeue, nil + } + + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterSecretReady, + Status: corev1.ConditionTrue, + }) + return reconcileStatusContinue, nil +} diff --git a/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_reconcile_deprovisioner.go b/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_reconcile_deprovisioner.go new file mode 100644 index 00000000000..cb72bafecf3 --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_reconcile_deprovisioner.go @@ -0,0 +1,115 @@ +/* +Copyright 2024 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 vcluster + +import ( + "context" + "fmt" + + conditionsapi "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/util/conditions" + "github.com/kcp-dev/logicalcluster/v3" + helmclient "github.com/mittwald/go-helm-client" + + corev1 "k8s.io/api/core/v1" + "k8s.io/klog/v2" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" +) + +const ( +// proxyPrefix = "/services/cluster-proxy/" +) + +// deprovisionerReconciler is a reconciler reconciles mounts deletes vcluster +// in the target cluster. +type deprovisionerReconciler struct { + getState func(key string) (state.Value, bool) +} + +func (r *deprovisionerReconciler) reconcile(ctx context.Context, mount *mountsv1alpha1.VCluster) (reconcileStatus, error) { + if mount.DeletionTimestamp == nil { // creation is handled by the provisioner. + return reconcileStatusContinue, nil + } + log := klog.FromContext(ctx) + + log.Info("deprovisioning vcluster", "name", mount.Name) + if mount.Spec.Mode != mountsv1alpha1.KubeClusterModeDelegated { + return reconcileStatusContinue, nil + } + + v, found := r.getState(*mount.Spec.SecretString) + if v.Client == nil || !found { + return reconcileStatusStopAndRequeue, nil + } + + cluster := logicalcluster.NewPath(logicalcluster.From(mount).String()) + + name := cluster.String() + mount.Name + + opt := &helmclient.RestConfClientOptions{ + Options: &helmclient.Options{ + Namespace: name, + RepositoryCache: "/tmp/.helmcache", + RepositoryConfig: "/tmp/.helmrepo", + Debug: true, + Linting: true, + }, + RestConfig: v.Config, + } + + helmClient, err := helmclient.NewClientFromRestConf(opt) + if err != nil { + return reconcileStatusStopAndRequeue, err + } + + releases, err := helmClient.ListDeployedReleases() + if err != nil { + return reconcileStatusStopAndRequeue, err + } + + var foundToDelete bool + for _, release := range releases { + if release.Name == "vcluster" && release.Namespace == name { + foundToDelete = true + chartSpec := &helmclient.ChartSpec{ + ReleaseName: "vcluster", + ChartName: "vcluster/vcluster", + Namespace: name, + CreateNamespace: true, + ValuesYaml: "", + Version: release.Chart.AppVersion(), + } + err := helmClient.UninstallRelease(chartSpec) + if err != nil { + klog.Warning(err) + return reconcileStatusStopAndRequeue, err + } + } + } + + if !foundToDelete { + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterDeleted, + Status: corev1.ConditionTrue, + Message: fmt.Sprintf("vclusters %s not found. Ready to be deleted.", name), + }) + } + + return reconcileStatusStopAndRequeue, nil // wait for all to be gone. +} diff --git a/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_reconcile_direct.go b/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_reconcile_direct.go new file mode 100644 index 00000000000..38257420b30 --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_reconcile_direct.go @@ -0,0 +1,150 @@ +/* +Copyright 2024 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 vcluster + +import ( + "context" + "fmt" + "net/url" + "path" + + tenancyv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/tenancy/v1alpha1" + conditionsapi "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/util/conditions" + "github.com/kcp-dev/logicalcluster/v3" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/utils/clientgo" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/utils/secrets" +) + +const ( + proxyPrefix = "/services/cluster-proxy/" +) + +// directReconciler is a reconciler reconciles mounts, which are direct and +// has secret set. +type directReconciler struct { + getState func(key string) (state.Value, bool) + setState func(key string, value state.Value) + getSecret func(ctx context.Context, cluster logicalcluster.Path, namespace, name string) (*corev1.Secret, error) + deleteState func(key string) + getVirtualWorkspaceURL func() *url.URL +} + +func (r *directReconciler) reconcile(ctx context.Context, mount *mountsv1alpha1.VCluster) (reconcileStatus, error) { + if mount.Spec.Mode != mountsv1alpha1.KubeClusterModeDirect { + return reconcileStatusContinue, nil + } + + mount.Status.Phase = tenancyv1alpha1.MountPhaseInitializing + + secretRef := mount.Spec.SecretRef + if secretRef == nil { + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterSecretReady, + Status: corev1.ConditionFalse, + Message: "secretRef is not set", + }) + return reconcileStatusStopAndRequeue, nil + } + + cluster := logicalcluster.NewPath(logicalcluster.From(mount).String()) + + // set secret first: + if mount.Status.SecretString == "" { + secretString, err := secrets.GenerateSecret(16) + if err != nil { + return reconcileStatusStopAndRequeue, err + } + mount.Status.SecretString = secretString + } + + secret, err := r.getSecret(ctx, cluster, secretRef.Namespace, secretRef.Name) + if err != nil { + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterSecretReady, + Status: corev1.ConditionFalse, + Message: fmt.Sprintf("failed to get secret %s/%s: %v", secretRef.Namespace, secretRef.Name, err), + }) + r.deleteState(mount.Status.SecretString) + return reconcileStatusStopAndRequeue, err + } + + if secret.Data["kubeconfig"] == nil { + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterSecretReady, + Status: corev1.ConditionFalse, + Message: fmt.Sprintf("secret %s/%s does not contain 'kubeconfig' key", secretRef.Namespace, secretRef.Name), + }) + r.deleteState(mount.Status.SecretString) + return reconcileStatusStopAndRequeue, nil + } + + clientset, rest, err := clientgo.GetClientFromKubeConfig(secret.Data["kubeconfig"]) + if err != nil { + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterSecretReady, + Status: corev1.ConditionFalse, + Message: fmt.Sprintf("failed to create client from kubeconfig in secret %s/%s: %v", secretRef.Namespace, secretRef.Name, err), + }) + r.deleteState(mount.Status.SecretString) + return reconcileStatusStopAndRequeue, err + } + + _, err = clientset.CoreV1().Namespaces().List(ctx, metav1.ListOptions{}) + if err != nil { + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterSecretReady, + Status: corev1.ConditionFalse, + Message: fmt.Sprintf("failed to access namespaces from kubeconfig in secret %s/%s: %v", secretRef.Namespace, secretRef.Name, err), + }) + r.deleteState(mount.Status.SecretString) + return reconcileStatusStopAndRequeue, err + } + + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterSecretReady, + Status: corev1.ConditionTrue, + Message: fmt.Sprintf("successfully accessed namespaces from kubeconfig in secret %s/%s", secretRef.Namespace, secretRef.Name), + }) + + // construct url for mount: + kubeClusterVirtualWorkspaceURL := r.getVirtualWorkspaceURL() + kubeClusterVirtualWorkspaceURL.Path = path.Join( + proxyPrefix, + logicalcluster.From(mount).String(), + "apis", + mountsv1alpha1.SchemeGroupVersion.String(), + "kubeclusters", + mount.Name, + "proxy", + ) + mount.Status.URL = kubeClusterVirtualWorkspaceURL.String() + + r.setState(mount.Status.SecretString, state.Value{ + Client: clientset, + URL: mount.Status.URL, + Config: rest, + }) + + return reconcileStatusContinue, nil +} diff --git a/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_reconcile_finalizer.go b/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_reconcile_finalizer.go new file mode 100644 index 00000000000..20859e44fbf --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_reconcile_finalizer.go @@ -0,0 +1,55 @@ +/* +Copyright 2024 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 vcluster + +import ( + "context" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + corev1 "k8s.io/api/core/v1" +) + +const finalizerName = "helm.mounts.contrib.kcp.io/finalizer" + +// finalizerReconciler is a reconciler which adds finalizer to the mount. +type finalizerReconciler struct{} + +func (r *finalizerReconciler) reconcile(ctx context.Context, mount *mountsv1alpha1.VCluster) (reconcileStatus, error) { + if mount.DeletionTimestamp != nil { + for _, c := range mount.Status.Conditions { + if c.Type == mountsv1alpha1.ClusterDeleted || c.Status == corev1.ConditionTrue { + // delete the finalizer + mount.Finalizers = nil + return reconcileStatusStopAndRequeue, nil + } + } + } + if containsString(mount.Finalizers, finalizerName) { + return reconcileStatusContinue, nil + } + mount.Finalizers = append(mount.Finalizers, finalizerName) + return reconcileStatusStopAndRequeue, nil +} + +func containsString(slice []string, s string) bool { + for _, e := range slice { + if e == s { + return true + } + } + return false +} diff --git a/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_reconcile_provisioner.go b/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_reconcile_provisioner.go new file mode 100644 index 00000000000..ce04edeecae --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/mounts/vcluster/mounts_reconcile_provisioner.go @@ -0,0 +1,188 @@ +/* +Copyright 2024 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 vcluster + +import ( + "context" + "fmt" + "net/url" + "strings" + + tenancyv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/tenancy/v1alpha1" + conditionsapi "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/util/conditions" + "github.com/kcp-dev/logicalcluster/v3" + helmclient "github.com/mittwald/go-helm-client" + "helm.sh/helm/v3/pkg/repo" + + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/klog/v2" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/utils/clientgo" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/utils/secrets" +) + +const ( +// proxyPrefix = "/services/cluster-proxy/" +) + +// provisionerReconciler is a reconciler reconciles mounts provisions vcluster +// in the target cluster. +// Responsible for mountsv1alpha1.ClusterReady +type provisionerReconciler struct { + getState func(key string) (state.Value, bool) + setState func(key string, value state.Value) +} + +func (r *provisionerReconciler) reconcile(ctx context.Context, mount *mountsv1alpha1.VCluster) (reconcileStatus, error) { + log := klog.FromContext(ctx) + if mount.DeletionTimestamp != nil || mount.Spec.Mode != mountsv1alpha1.KubeClusterModeDelegated { // deletion is handled by the deprovisioner. + return reconcileStatusContinue, nil + } + + v, found := r.getState(*mount.Spec.SecretString) + if v.Client == nil || !found { + return reconcileStatusStopAndRequeue, nil + } + + cluster := logicalcluster.NewPath(logicalcluster.From(mount).String()) + + name := cluster.String() + mount.Name + + opt := &helmclient.RestConfClientOptions{ + Options: &helmclient.Options{ + Namespace: name, + RepositoryCache: "/tmp/.helmcache", + RepositoryConfig: "/tmp/.helmrepo", + Debug: true, + Linting: true, + }, + RestConfig: v.Config, + } + + helmClient, err := helmclient.NewClientFromRestConf(opt) + if err != nil { + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterReady, + Status: corev1.ConditionFalse, + Message: fmt.Errorf("failed to setup helm client: %v", err).Error(), + }) + return reconcileStatusStopAndRequeue, err + } + + // Add the repository where the chart is located + err = helmClient.AddOrUpdateChartRepo(repo.Entry{ + Name: "vcluster", + URL: "https://charts.loft.sh", + }) + if err != nil { + if !strings.Contains(err.Error(), "already exists") { + return reconcileStatusStopAndRequeue, err + } + } + + releases, err := helmClient.ListDeployedReleases() + if err != nil { + return reconcileStatusStopAndRequeue, err + } + + var foundHelm bool + for _, release := range releases { + if release.Name == "vcluster" && release.Namespace == name { + if release.Chart.AppVersion() == "0.20.2" { + log.V(2).Info("vcluster already installed desired version") + foundHelm = true + } + } + } + + if !foundHelm { + log.V(2).Info("vcluster installing/upgrading") + // Define the chart specification + chartSpec := &helmclient.ChartSpec{ + ReleaseName: "vcluster", + ChartName: "vcluster/vcluster", + Namespace: name, + CreateNamespace: true, + ValuesYaml: "", + Version: mount.Spec.Version, + } + + // Install the Helm chart + _, err = helmClient.InstallOrUpgradeChart(ctx, chartSpec, nil) + if err != nil { + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterReady, + Status: corev1.ConditionFalse, + Message: fmt.Errorf("failed to install vcluster: %v", err).Error(), + }) + return reconcileStatusStopAndRequeue, err + } + } + + // get configMap with kubeconfig + secret, err := v.Client.CoreV1().Secrets(name).Get(ctx, "vc-vcluster", metav1.GetOptions{}) + if err != nil { + if apierrors.IsNotFound(err) { + return reconcileStatusStopAndRequeue, nil + } + return reconcileStatusStopAndRequeue, err + } + + _, rest, err := clientgo.GetClientFromKubeConfig(secret.Data["config"]) + if err != nil { + return reconcileStatusStopAndRequeue, err + } + + v.VClusterConfig = rest + v.VClusterNamespace = name + + var secretString string + if mount.Status.SecretString == "" { + secretString, err = secrets.GenerateSecret(16) + if err != nil { + return reconcileStatusStopAndRequeue, err + } + mount.Status.SecretString = secretString + r.setState(secretString, v) + } else { + secretString = mount.Status.SecretString + } + + r.setState(secretString, v) + + // secrets string will be purged at VW side. + // TOOD: This is a temporary solution. We need to find a better way to handle this. + full, err := url.JoinPath(v.URL, "secret", secretString) + if err != nil { + return reconcileStatusStopAndRequeue, err + } + mount.Status.URL = full + mount.Status.Phase = tenancyv1alpha1.MountPhaseReady + + conditions.Set(mount, &conditionsapi.Condition{ + Type: mountsv1alpha1.ClusterReady, + Status: corev1.ConditionTrue, + }) + mount.Status.Phase = tenancyv1alpha1.MountPhaseReady + + return reconcileStatusContinue, nil +} diff --git a/contrib/mounts-virtualworkspace/reconciler/targets/README.md b/contrib/mounts-virtualworkspace/reconciler/targets/README.md new file mode 100644 index 00000000000..4423c45552b --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/targets/README.md @@ -0,0 +1,7 @@ +# Targets reconciler + +Targets reconciles the targets in the specific workspace and does the following: + +- checks if secret is present +- check if the target cluster is healthy +- generates random secret string to be used by mounts diff --git a/contrib/mounts-virtualworkspace/reconciler/targets/kubecluster/targets_controller.go b/contrib/mounts-virtualworkspace/reconciler/targets/kubecluster/targets_controller.go new file mode 100644 index 00000000000..35d5f800f85 --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/targets/kubecluster/targets_controller.go @@ -0,0 +1,208 @@ +/* +Copyright 2024 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 kubercluster + +import ( + "context" + "fmt" + "time" + + kcpcache "github.com/kcp-dev/apimachinery/v2/pkg/cache" + kcpdynamic "github.com/kcp-dev/client-go/dynamic" + kcpkubernetesclientset "github.com/kcp-dev/client-go/kubernetes" + "github.com/kcp-dev/kcp/pkg/informer" + "github.com/kcp-dev/kcp/pkg/logging" + "github.com/kcp-dev/kcp/pkg/reconciler/committer" + kcpclientset "github.com/kcp-dev/kcp/sdk/client/clientset/versioned/cluster" + + kerrors "k8s.io/apimachinery/pkg/api/errors" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog/v2" + + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" + mountsclientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster" + targetsv1alpha1client "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1" + targetsv1alpha1informers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions/targets/v1alpha1" + targetsv1alpha1listers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/listers/targets/v1alpha1" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" +) + +const ( + // ControllerName is the name of this controller. + ControllerName = "kcp-targets-kubeclusters" +) + +// NewController creates a new controller for targets. +func NewController( + kcpClusterClient kcpclientset.ClusterInterface, + mountsClusterClient mountsclientset.ClusterInterface, + kubeClusterClient kcpkubernetesclientset.ClusterInterface, + dynamicClusterClient kcpdynamic.ClusterInterface, + targetsInformers targetsv1alpha1informers.TargetKubeClusterClusterInformer, + store state.ClientSetStoreInterface, + virtualWorkspaceURL string, +) (*Controller, error) { + c := &Controller{ + queue: workqueue.NewTypedRateLimitingQueueWithConfig( + workqueue.DefaultTypedControllerRateLimiter[string](), + workqueue.TypedRateLimitingQueueConfig[string]{ + Name: ControllerName, + }, + ), + virtualWorkspaceURL: virtualWorkspaceURL, + store: store, + + dynamicClusterClient: dynamicClusterClient, + kubeClusterClient: kubeClusterClient, + + targetsIndexer: targetsInformers.Informer().GetIndexer(), + targetsLister: targetsInformers.Lister(), + + commit: committer.NewCommitter[*targetsv1alpha1.TargetKubeCluster, targetsv1alpha1client.TargetKubeClusterInterface, *targetsv1alpha1.TargetKubeClusterSpec, *targetsv1alpha1.TargetKubeClusterStatus](mountsClusterClient.TargetsV1alpha1().TargetKubeClusters()), + } + + _, _ = targetsInformers.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { c.enqueue(obj) }, + UpdateFunc: func(_, obj interface{}) { c.enqueue(obj) }, + }) + + return c, nil +} + +type targetResource = committer.Resource[*targetsv1alpha1.TargetKubeClusterSpec, *targetsv1alpha1.TargetKubeClusterStatus] + +// Controller watches Targets and dynamically discovered mount resources and reconciles them so +// workspace has right annotations. +type Controller struct { + // queue is the work-queue used by the controller + queue workqueue.TypedRateLimitingInterface[string] + store state.ClientSetStoreInterface + virtualWorkspaceURL string + + dynamicClusterClient kcpdynamic.ClusterInterface + kubeClusterClient kcpkubernetesclientset.ClusterInterface + + discoveringDynamicSharedInformerFactory *informer.DiscoveringDynamicSharedInformerFactory + + targetsIndexer cache.Indexer + targetsLister targetsv1alpha1listers.TargetKubeClusterClusterLister + + // commit creates a patch and submits it, if needed. + commit func(ctx context.Context, new, old *targetResource) error +} + +// enqueue adds the object to the work queue. +func (c *Controller) enqueue(obj interface{}) { + key, err := kcpcache.MetaClusterNamespaceKeyFunc(obj) + if err != nil { + runtime.HandleError(err) + return + } + logger := logging.WithQueueKey(logging.WithReconciler(klog.Background(), ControllerName), key) + logger.V(4).Info("queueing Target") + c.queue.Add(key) +} + +func (c *Controller) Start(ctx context.Context, numThreads int) { + defer runtime.HandleCrash() + defer c.queue.ShutDown() + + logger := logging.WithReconciler(klog.FromContext(ctx), ControllerName) + ctx = klog.NewContext(ctx, logger) + logger.Info("Starting controller") + defer logger.Info("Shutting down controller") + + for i := 0; i < numThreads; i++ { + go wait.Until(func() { c.startWorker(ctx) }, time.Second, ctx.Done()) + } + + <-ctx.Done() +} + +func (c *Controller) startWorker(ctx context.Context) { + for c.processNextWorkItem(ctx) { + } +} + +func (c *Controller) processNextWorkItem(ctx context.Context) bool { + // Wait until there is a new item in the working queue + k, quit := c.queue.Get() + if quit { + return false + } + key := k + + logger := logging.WithQueueKey(klog.FromContext(ctx), key) + ctx = klog.NewContext(ctx, logger) + logger.V(4).Info("processing key") + + // No matter what, tell the queue we're done with this key, to unblock + // other workers. + defer c.queue.Done(key) + + if requeue, err := c.process(ctx, key); err != nil { + runtime.HandleError(fmt.Errorf("%q controller failed to sync %q, err: %w", ControllerName, key, err)) + c.queue.AddRateLimited(key) + return true + } else if requeue { + // only requeue if we didn't error, but we still want to requeue + c.queue.Add(key) + return true + } + c.queue.Forget(key) + return true +} + +func (c *Controller) process(ctx context.Context, key string) (bool, error) { + parent, _, name, err := kcpcache.SplitMetaClusterNamespaceKey(key) + if err != nil { + return false, err + } + + target, err := c.targetsLister.Cluster(parent).Get(name) + if err != nil { + if kerrors.IsNotFound(err) { + return false, nil // object deleted before we handled it + } + return false, err + } + + old := target + target = target.DeepCopy() + + logger := logging.WithObject(klog.FromContext(ctx), target) + ctx = klog.NewContext(ctx, logger) + + var errs []error + requeue, err := c.reconcile(ctx, target) + if err != nil { + errs = append(errs, err) + } + + // If the object being reconciled changed as a result, update it. + oldResource := &targetResource{ObjectMeta: old.ObjectMeta, Spec: &old.Spec, Status: &old.Status} + newResource := &targetResource{ObjectMeta: target.ObjectMeta, Spec: &target.Spec, Status: &target.Status} + if err := c.commit(ctx, oldResource, newResource); err != nil { + errs = append(errs, err) + } + + return requeue, utilerrors.NewAggregate(errs) +} diff --git a/contrib/mounts-virtualworkspace/reconciler/targets/kubecluster/targets_reconcile.go b/contrib/mounts-virtualworkspace/reconciler/targets/kubecluster/targets_reconcile.go new file mode 100644 index 00000000000..37317cbe1e4 --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/targets/kubecluster/targets_reconcile.go @@ -0,0 +1,88 @@ +/* +Copyright 2024 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 kubercluster + +import ( + "context" + "net/url" + + "github.com/kcp-dev/logicalcluster/v3" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilserrors "k8s.io/apimachinery/pkg/util/errors" + + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" +) + +type reconcileStatus int + +const ( + reconcileStatusStopAndRequeue reconcileStatus = iota + reconcileStatusContinue +) + +type reconciler interface { + reconcile(ctx context.Context, target *targetsv1alpha1.TargetKubeCluster) (reconcileStatus, error) +} + +// reconcile reconciles the workspace objects. It is intended to be single reconciler for all the +// workspace replated operations. For now it has single reconciler that updates the status of the +// workspace based on the mount status. +func (c *Controller) reconcile(ctx context.Context, target *targetsv1alpha1.TargetKubeCluster) (bool, error) { + + u, err := url.Parse(c.virtualWorkspaceURL) + if err != nil { + return false, err + } + + reconcilers := []reconciler{ + &targetSecretReconciler{ + getSecret: func(ctx context.Context, cluster logicalcluster.Path, namespaces, name string) (*corev1.Secret, error) { + return c.kubeClusterClient.CoreV1().Cluster(cluster).Secrets(namespaces).Get(ctx, name, metav1.GetOptions{}) + }, + setState: func(key string, value state.Value) { + c.store.Set(state.KindKubeClusters, key, value) + }, + deleteState: func(key string) { + c.store.Delete(state.KindKubeClusters, key) + }, + getVirtualWorkspaceURL: func() *url.URL { + return u + }, + }, + } + + var errs []error + + requeue := false + for _, r := range reconcilers { + var err error + var status reconcileStatus + status, err = r.reconcile(ctx, target) + if err != nil { + errs = append(errs, err) + } + if status == reconcileStatusStopAndRequeue { + requeue = true + break + } + } + + return requeue, utilserrors.NewAggregate(errs) +} diff --git a/contrib/mounts-virtualworkspace/reconciler/targets/kubecluster/targets_reconcile_setter.go b/contrib/mounts-virtualworkspace/reconciler/targets/kubecluster/targets_reconcile_setter.go new file mode 100644 index 00000000000..5d635474e1c --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/targets/kubecluster/targets_reconcile_setter.go @@ -0,0 +1,135 @@ +/* +Copyright 2024 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 kubercluster + +import ( + "context" + "fmt" + "net/url" + "path" + + tenancyv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/tenancy/v1alpha1" + conditionsapi "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/util/conditions" + "github.com/kcp-dev/logicalcluster/v3" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/utils/clientgo" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/utils/secrets" +) + +type targetSecretReconciler struct { + getSecret func(ctx context.Context, cluster logicalcluster.Path, namespace, name string) (*corev1.Secret, error) + setState func(key string, value state.Value) + deleteState func(key string) + getVirtualWorkspaceURL func() *url.URL +} + +const ( + proxyPrefix = "/services/cluster-proxy/" +) + +func (r *targetSecretReconciler) reconcile(ctx context.Context, target *targetsv1alpha1.TargetKubeCluster) (reconcileStatus, error) { + secretRef := target.Spec.SecretRef + cluster := logicalcluster.NewPath(logicalcluster.From(target).String()) + + target.Status.Phase = tenancyv1alpha1.MountPhaseConnecting + + // set secret first: + if target.Status.SecretString == "" { + secretString, err := secrets.GenerateSecret(16) + if err != nil { + return reconcileStatusStopAndRequeue, err + } + target.Status.SecretString = secretString + } + + secret, err := r.getSecret(ctx, cluster, secretRef.Namespace, secretRef.Name) + if err != nil { + conditions.Set(target, &conditionsapi.Condition{ + Type: targetsv1alpha1.ClusterReady, + Status: corev1.ConditionFalse, + Message: fmt.Sprintf("failed to get secret %s/%s: %v", secretRef.Namespace, secretRef.Name, err), + }) + r.deleteState(target.Status.SecretString) + return reconcileStatusStopAndRequeue, err + } + + if secret.Data["kubeconfig"] == nil { + conditions.Set(target, &conditionsapi.Condition{ + Type: targetsv1alpha1.ClusterReady, + Status: corev1.ConditionFalse, + Message: fmt.Sprintf("secret %s/%s does not contain 'kubeconfig' key", secretRef.Namespace, secretRef.Name), + }) + r.deleteState(target.Status.SecretString) + return reconcileStatusStopAndRequeue, nil + } + + clientset, rest, err := clientgo.GetClientFromKubeConfig(secret.Data["kubeconfig"]) + if err != nil { + conditions.Set(target, &conditionsapi.Condition{ + Type: targetsv1alpha1.ClusterReady, + Status: corev1.ConditionFalse, + Message: fmt.Sprintf("failed to create client from kubeconfig in secret %s/%s: %v", secretRef.Namespace, secretRef.Name, err), + }) + r.deleteState(target.Status.SecretString) + return reconcileStatusStopAndRequeue, err + } + + _, err = clientset.CoreV1().Namespaces().List(ctx, metav1.ListOptions{}) + if err != nil { + conditions.Set(target, &conditionsapi.Condition{ + Type: targetsv1alpha1.ClusterReady, + Status: corev1.ConditionFalse, + Message: fmt.Sprintf("failed to access namespaces from kubeconfig in secret %s/%s: %v", secretRef.Namespace, secretRef.Name, err), + }) + r.deleteState(target.Status.SecretString) + return reconcileStatusStopAndRequeue, err + } + + conditions.Set(target, &conditionsapi.Condition{ + Type: targetsv1alpha1.ClusterReady, + Status: corev1.ConditionTrue, + Message: fmt.Sprintf("successfully accessed namespaces from kubeconfig in secret %s/%s", secretRef.Namespace, secretRef.Name), + }) + + // construct url for mount: + kubeClusterVirtualWorkspaceURL := r.getVirtualWorkspaceURL() + kubeClusterVirtualWorkspaceURL.Path = path.Join( + proxyPrefix, + logicalcluster.From(target).String(), + "apis", + targetsv1alpha1.SchemeGroupVersion.String(), + "kubeclusters", + target.Name, + "proxy", + ) + target.Status.URL = kubeClusterVirtualWorkspaceURL.String() + + r.setState(target.Status.SecretString, state.Value{ + Client: clientset, + URL: target.Status.URL, + Config: rest, + }) + target.Status.Phase = tenancyv1alpha1.MountPhaseReady + + return reconcileStatusContinue, nil +} diff --git a/contrib/mounts-virtualworkspace/reconciler/targets/vcluster/targets_controller.go b/contrib/mounts-virtualworkspace/reconciler/targets/vcluster/targets_controller.go new file mode 100644 index 00000000000..d1156e06bb6 --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/targets/vcluster/targets_controller.go @@ -0,0 +1,208 @@ +/* +Copyright 2024 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 vcluster + +import ( + "context" + "fmt" + "time" + + kcpcache "github.com/kcp-dev/apimachinery/v2/pkg/cache" + kcpdynamic "github.com/kcp-dev/client-go/dynamic" + kcpkubernetesclientset "github.com/kcp-dev/client-go/kubernetes" + "github.com/kcp-dev/kcp/pkg/informer" + "github.com/kcp-dev/kcp/pkg/logging" + "github.com/kcp-dev/kcp/pkg/reconciler/committer" + kcpclientset "github.com/kcp-dev/kcp/sdk/client/clientset/versioned/cluster" + + kerrors "k8s.io/apimachinery/pkg/api/errors" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog/v2" + + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" + mountsclientset "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/cluster" + targetsv1alpha1client "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/clientset/versioned/typed/targets/v1alpha1" + targetsv1alpha1informers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions/targets/v1alpha1" + targetsv1alpha1listers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/listers/targets/v1alpha1" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" +) + +const ( + // ControllerName is the name of this controller. + ControllerName = "kcp-targets-vcluster" +) + +// NewController creates a new controller for targets. +func NewController( + kcpClusterClient kcpclientset.ClusterInterface, + mountsClusterClient mountsclientset.ClusterInterface, + kubeClusterClient kcpkubernetesclientset.ClusterInterface, + dynamicClusterClient kcpdynamic.ClusterInterface, + targetsInformers targetsv1alpha1informers.TargetVClusterClusterInformer, + store state.ClientSetStoreInterface, + virtualWorkspaceURL string, +) (*Controller, error) { + c := &Controller{ + queue: workqueue.NewTypedRateLimitingQueueWithConfig( + workqueue.DefaultTypedControllerRateLimiter[string](), + workqueue.TypedRateLimitingQueueConfig[string]{ + Name: ControllerName, + }, + ), + virtualWorkspaceURL: virtualWorkspaceURL, + store: store, + + dynamicClusterClient: dynamicClusterClient, + kubeClusterClient: kubeClusterClient, + + targetsIndexer: targetsInformers.Informer().GetIndexer(), + targetsLister: targetsInformers.Lister(), + + commit: committer.NewCommitter[*targetsv1alpha1.TargetVCluster, targetsv1alpha1client.TargetVClusterInterface, *targetsv1alpha1.TargetVClusterSpec, *targetsv1alpha1.TargetVClusterStatus](mountsClusterClient.TargetsV1alpha1().TargetVClusters()), + } + + _, _ = targetsInformers.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { c.enqueue(obj) }, + UpdateFunc: func(_, obj interface{}) { c.enqueue(obj) }, + }) + + return c, nil +} + +type targetResource = committer.Resource[*targetsv1alpha1.TargetVClusterSpec, *targetsv1alpha1.TargetVClusterStatus] + +// Controller watches Targets and dynamically discovered mount resources and reconciles them so +// workspace has right annotations. +type Controller struct { + // queue is the work-queue used by the controller + queue workqueue.TypedRateLimitingInterface[string] + store state.ClientSetStoreInterface + virtualWorkspaceURL string + + dynamicClusterClient kcpdynamic.ClusterInterface + kubeClusterClient kcpkubernetesclientset.ClusterInterface + + discoveringDynamicSharedInformerFactory *informer.DiscoveringDynamicSharedInformerFactory + + targetsIndexer cache.Indexer + targetsLister targetsv1alpha1listers.TargetVClusterClusterLister + + // commit creates a patch and submits it, if needed. + commit func(ctx context.Context, new, old *targetResource) error +} + +// enqueue adds the object to the work queue. +func (c *Controller) enqueue(obj interface{}) { + key, err := kcpcache.MetaClusterNamespaceKeyFunc(obj) + if err != nil { + runtime.HandleError(err) + return + } + logger := logging.WithQueueKey(logging.WithReconciler(klog.Background(), ControllerName), key) + logger.V(4).Info("queueing Target") + c.queue.Add(key) +} + +func (c *Controller) Start(ctx context.Context, numThreads int) { + defer runtime.HandleCrash() + defer c.queue.ShutDown() + + logger := logging.WithReconciler(klog.FromContext(ctx), ControllerName) + ctx = klog.NewContext(ctx, logger) + logger.Info("Starting controller") + defer logger.Info("Shutting down controller") + + for i := 0; i < numThreads; i++ { + go wait.Until(func() { c.startWorker(ctx) }, time.Second, ctx.Done()) + } + + <-ctx.Done() +} + +func (c *Controller) startWorker(ctx context.Context) { + for c.processNextWorkItem(ctx) { + } +} + +func (c *Controller) processNextWorkItem(ctx context.Context) bool { + // Wait until there is a new item in the working queue + k, quit := c.queue.Get() + if quit { + return false + } + key := k + + logger := logging.WithQueueKey(klog.FromContext(ctx), key) + ctx = klog.NewContext(ctx, logger) + logger.V(4).Info("processing key") + + // No matter what, tell the queue we're done with this key, to unblock + // other workers. + defer c.queue.Done(key) + + if requeue, err := c.process(ctx, key); err != nil { + runtime.HandleError(fmt.Errorf("%q controller failed to sync %q, err: %w", ControllerName, key, err)) + c.queue.AddRateLimited(key) + return true + } else if requeue { + // only requeue if we didn't error, but we still want to requeue + c.queue.Add(key) + return true + } + c.queue.Forget(key) + return true +} + +func (c *Controller) process(ctx context.Context, key string) (bool, error) { + parent, _, name, err := kcpcache.SplitMetaClusterNamespaceKey(key) + if err != nil { + return false, err + } + + target, err := c.targetsLister.Cluster(parent).Get(name) + if err != nil { + if kerrors.IsNotFound(err) { + return false, nil // object deleted before we handled it + } + return false, err + } + + old := target + target = target.DeepCopy() + + logger := logging.WithObject(klog.FromContext(ctx), target) + ctx = klog.NewContext(ctx, logger) + + var errs []error + requeue, err := c.reconcile(ctx, target) + if err != nil { + errs = append(errs, err) + } + + // If the object being reconciled changed as a result, update it. + oldResource := &targetResource{ObjectMeta: old.ObjectMeta, Spec: &old.Spec, Status: &old.Status} + newResource := &targetResource{ObjectMeta: target.ObjectMeta, Spec: &target.Spec, Status: &target.Status} + if err := c.commit(ctx, oldResource, newResource); err != nil { + errs = append(errs, err) + } + + return requeue, utilerrors.NewAggregate(errs) +} diff --git a/contrib/mounts-virtualworkspace/reconciler/targets/vcluster/targets_reconcile.go b/contrib/mounts-virtualworkspace/reconciler/targets/vcluster/targets_reconcile.go new file mode 100644 index 00000000000..b3442a6bc78 --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/targets/vcluster/targets_reconcile.go @@ -0,0 +1,88 @@ +/* +Copyright 2024 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 vcluster + +import ( + "context" + "net/url" + + "github.com/kcp-dev/logicalcluster/v3" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilserrors "k8s.io/apimachinery/pkg/util/errors" + + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" +) + +type reconcileStatus int + +const ( + reconcileStatusStopAndRequeue reconcileStatus = iota + reconcileStatusContinue +) + +type reconciler interface { + reconcile(ctx context.Context, target *targetsv1alpha1.TargetVCluster) (reconcileStatus, error) +} + +// reconcile reconciles the workspace objects. It is intended to be single reconciler for all the +// workspace replated operations. For now it has single reconciler that updates the status of the +// workspace based on the mount status. +func (c *Controller) reconcile(ctx context.Context, target *targetsv1alpha1.TargetVCluster) (bool, error) { + + u, err := url.Parse(c.virtualWorkspaceURL) + if err != nil { + return false, err + } + + reconcilers := []reconciler{ + &targetSecretReconciler{ + getSecret: func(ctx context.Context, cluster logicalcluster.Path, namespaces, name string) (*corev1.Secret, error) { + return c.kubeClusterClient.CoreV1().Cluster(cluster).Secrets(namespaces).Get(ctx, name, metav1.GetOptions{}) + }, + setState: func(key string, value state.Value) { + c.store.Set(state.KindVClusters, key, value) + }, + deleteState: func(key string) { + c.store.Delete(state.KindVClusters, key) + }, + getVirtualWorkspaceURL: func() *url.URL { + return u + }, + }, + } + + var errs []error + + requeue := false + for _, r := range reconcilers { + var err error + var status reconcileStatus + status, err = r.reconcile(ctx, target) + if err != nil { + errs = append(errs, err) + } + if status == reconcileStatusStopAndRequeue { + requeue = true + break + } + } + + return requeue, utilserrors.NewAggregate(errs) +} diff --git a/contrib/mounts-virtualworkspace/reconciler/targets/vcluster/targets_reconcile_setter.go b/contrib/mounts-virtualworkspace/reconciler/targets/vcluster/targets_reconcile_setter.go new file mode 100644 index 00000000000..f411d844dd2 --- /dev/null +++ b/contrib/mounts-virtualworkspace/reconciler/targets/vcluster/targets_reconcile_setter.go @@ -0,0 +1,135 @@ +/* +Copyright 2024 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 vcluster + +import ( + "context" + "fmt" + "net/url" + "path" + + conditionsapi "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/util/conditions" + "github.com/kcp-dev/logicalcluster/v3" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/utils/clientgo" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/utils/secrets" +) + +type targetSecretReconciler struct { + getSecret func(ctx context.Context, cluster logicalcluster.Path, namespace, name string) (*corev1.Secret, error) + setState func(key string, value state.Value) + deleteState func(key string) + getVirtualWorkspaceURL func() *url.URL +} + +const ( + proxyPrefix = "/services/cluster-proxy/" +) + +func (r *targetSecretReconciler) reconcile(ctx context.Context, target *targetsv1alpha1.TargetVCluster) (reconcileStatus, error) { + secretRef := target.Spec.SecretRef + cluster := logicalcluster.NewPath(logicalcluster.From(target).String()) + + target.Status.Phase = targetsv1alpha1.PhaseInitializing + + // set secret first: + if target.Status.SecretString == "" { + secretString, err := secrets.GenerateSecret(16) + if err != nil { + return reconcileStatusStopAndRequeue, err + } + target.Status.SecretString = secretString + } + + secret, err := r.getSecret(ctx, cluster, secretRef.Namespace, secretRef.Name) + if err != nil { + conditions.Set(target, &conditionsapi.Condition{ + Type: targetsv1alpha1.ClusterReady, + Status: corev1.ConditionFalse, + Message: fmt.Sprintf("failed to get secret %s/%s: %v", secretRef.Namespace, secretRef.Name, err), + }) + r.deleteState(target.Status.SecretString) + return reconcileStatusStopAndRequeue, err + } + + if secret.Data["kubeconfig"] == nil { + conditions.Set(target, &conditionsapi.Condition{ + Type: targetsv1alpha1.ClusterReady, + Status: corev1.ConditionFalse, + Message: fmt.Sprintf("secret %s/%s does not contain 'kubeconfig' key", secretRef.Namespace, secretRef.Name), + }) + r.deleteState(target.Status.SecretString) + return reconcileStatusStopAndRequeue, nil + } + + clientset, rest, err := clientgo.GetClientFromKubeConfig(secret.Data["kubeconfig"]) + if err != nil { + conditions.Set(target, &conditionsapi.Condition{ + Type: targetsv1alpha1.ClusterReady, + Status: corev1.ConditionFalse, + Message: fmt.Sprintf("failed to create client from kubeconfig in secret %s/%s: %v", secretRef.Namespace, secretRef.Name, err), + }) + r.deleteState(target.Status.SecretString) + return reconcileStatusStopAndRequeue, err + } + + _, err = clientset.CoreV1().Namespaces().List(ctx, metav1.ListOptions{}) + if err != nil { + conditions.Set(target, &conditionsapi.Condition{ + Type: targetsv1alpha1.ClusterReady, + Status: corev1.ConditionFalse, + Message: fmt.Sprintf("failed to access namespaces from kubeconfig in secret %s/%s: %v", secretRef.Namespace, secretRef.Name, err), + }) + r.deleteState(target.Status.SecretString) + target.Status.Phase = targetsv1alpha1.PhaseInitializing + return reconcileStatusStopAndRequeue, err + } + + conditions.Set(target, &conditionsapi.Condition{ + Type: targetsv1alpha1.ClusterReady, + Status: corev1.ConditionTrue, + Message: fmt.Sprintf("successfully accessed namespaces from kubeconfig in secret %s/%s", secretRef.Namespace, secretRef.Name), + }) + + // construct url for mount: + kubeClusterVirtualWorkspaceURL := r.getVirtualWorkspaceURL() + kubeClusterVirtualWorkspaceURL.Path = path.Join( + proxyPrefix, + logicalcluster.From(target).String(), + "apis", + targetsv1alpha1.SchemeGroupVersion.String(), + "vclusters", + target.Name, + "proxy", + ) + target.Status.URL = kubeClusterVirtualWorkspaceURL.String() + + r.setState(target.Status.SecretString, state.Value{ + Client: clientset, + URL: target.Status.URL, + Config: rest, + }) + target.Status.Phase = targetsv1alpha1.PhaseReady + + return reconcileStatusContinue, nil +} diff --git a/contrib/mounts-virtualworkspace/state/state.go b/contrib/mounts-virtualworkspace/state/state.go new file mode 100644 index 00000000000..1932d47e084 --- /dev/null +++ b/contrib/mounts-virtualworkspace/state/state.go @@ -0,0 +1,69 @@ +package state + +import ( + "sync" + + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" +) + +// ClientSetStoreInterface defines the interface for storing and retrieving Kubernetes clientsets +type ClientSetStoreInterface interface { + Set(kind Kind, key string, value Value) + Get(kind Kind, key string) (Value, bool) + Delete(kind Kind, key string) +} + +type Kind string + +const ( + KindKubeClusters Kind = "kubeclusters" + KindVClusters Kind = "vclusters" +) + +type Value struct { + Client *kubernetes.Clientset + Config *rest.Config + VClusterConfig *rest.Config + VClusterNamespace string + URL string +} + +// ClientSetStore provides a thread-safe in-memory store for Kubernetes clientsets +type ClientSetStore struct { + store map[string]Value + mu sync.RWMutex +} + +// NewClientSetStore initializes a new ClientSetStore +func NewClientSetStore() *ClientSetStore { + return &ClientSetStore{ + store: make(map[string]Value), + } +} + +// Set stores a clientset with the associated key, ensuring write-locking for thread safety +func (c *ClientSetStore) Set(kind Kind, key string, value Value) { + c.mu.Lock() + defer c.mu.Unlock() + c.store[getKey(kind, key)] = value +} + +// Get retrieves the clientset associated with the key, ensuring read-locking for thread safety +func (c *ClientSetStore) Get(kind Kind, key string) (Value, bool) { + c.mu.RLock() + defer c.mu.RUnlock() + v, exists := c.store[getKey(kind, key)] + return v, exists +} + +// Delete removes a clientset associated with the key, if it exists +func (c *ClientSetStore) Delete(kind Kind, key string) { + c.mu.Lock() + defer c.mu.Unlock() + delete(c.store, getKey(kind, key)) +} + +func getKey(kind Kind, key string) string { + return string(kind) + ":" + key +} diff --git a/contrib/mounts-virtualworkspace/utils/clientgo/client.go b/contrib/mounts-virtualworkspace/utils/clientgo/client.go new file mode 100644 index 00000000000..38a34f8f4d2 --- /dev/null +++ b/contrib/mounts-virtualworkspace/utils/clientgo/client.go @@ -0,0 +1,22 @@ +package clientgo + +import ( + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" +) + +// GetClientFromKubeConfig creates a new kubernetes client from a kubeconfig. +func GetClientFromKubeConfig(kubeconfig []byte) (*kubernetes.Clientset, *rest.Config, error) { + config, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig) + if err != nil { + return nil, nil, err + } + + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + return nil, nil, err + } + + return clientset, config, nil +} diff --git a/contrib/mounts-virtualworkspace/utils/portforward/dial.go b/contrib/mounts-virtualworkspace/utils/portforward/dial.go new file mode 100644 index 00000000000..a9b4a47b8df --- /dev/null +++ b/contrib/mounts-virtualworkspace/utils/portforward/dial.go @@ -0,0 +1,113 @@ +package portforward + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +import ( + "bufio" + "context" + "crypto/tls" + "fmt" + "net" + "net/http" + "net/url" + "time" + + "k8s.io/apimachinery/pkg/util/httpstream" + "k8s.io/apimachinery/pkg/util/httpstream/spdy" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/portforward" +) + +// dialSpdy connects to the specified path on the API server of oc and +// negotiates SPDY +func dialSpdy(ctx context.Context, restconfig *rest.Config, path string) (httpstream.Connection, error) { + // 1. Connect to the API server via private endpoint (and via proxy in + // development mode) + clusterURL, err := url.Parse(restconfig.Host) + if err != nil { + return nil, err + } + + dialContext := restconfig.Dial + if dialContext == nil { + dialContext = (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + }).DialContext + } + + rawConn, err := dialContext(ctx, "tcp", clusterURL.Host) + if err != nil { + return nil, err + } + + // 2. Negotiate TLS + tlsConfig, err := rest.TLSConfigFor(restconfig) + if err != nil { + rawConn.Close() + return nil, err + } + if tlsConfig == nil { + tlsConfig = &tls.Config{} + } + tlsConfig.ServerName = clusterURL.Hostname() + //tlsConfig.InsecureSkipVerify = true + + tlsConn := tls.Client(rawConn, tlsConfig) + err = tlsConn.Handshake() + if err != nil { + tlsConn.Close() + return nil, err + } + + // 3. Issue an HTTP POST request to the specified path + req, err := http.NewRequest(http.MethodPost, path, nil) + if err != nil { + tlsConn.Close() + return nil, err + } + req.Header.Add(httpstream.HeaderConnection, httpstream.HeaderUpgrade) + req.Header.Add(httpstream.HeaderProtocolVersion, portforward.PortForwardProtocolV1Name) + req.Header.Add(httpstream.HeaderUpgrade, spdy.HeaderSpdy31) + if restconfig.BearerToken != "" { + req.Header.Add("Authorization", "Bearer "+restconfig.BearerToken) + } + + err = req.Write(tlsConn) + if err != nil { + tlsConn.Close() + return nil, err + } + + // 4. Validate the response + resp, err := http.ReadResponse(bufio.NewReader(tlsConn), req) + if err != nil { + tlsConn.Close() + return nil, err + } + + if resp.StatusCode != http.StatusSwitchingProtocols { + tlsConn.Close() + return nil, fmt.Errorf("unexpected http status code %d", resp.StatusCode) + } + + if resp.Header.Get(httpstream.HeaderConnection) != httpstream.HeaderUpgrade { + tlsConn.Close() + return nil, fmt.Errorf("unexpected http header %s: %s", httpstream.HeaderConnection, resp.Header.Get(httpstream.HeaderConnection)) + } + + if resp.Header.Get(httpstream.HeaderUpgrade) != spdy.HeaderSpdy31 { + tlsConn.Close() + return nil, fmt.Errorf("unexpected http header %s: %s", httpstream.HeaderUpgrade, resp.Header.Get(httpstream.HeaderUpgrade)) + } + + // 5. Negotiate SPDY + spdyConn, err := spdy.NewClientConnection(tlsConn) + if err != nil { + tlsConn.Close() + return nil, err + } + + return spdyConn, nil +} diff --git a/contrib/mounts-virtualworkspace/utils/portforward/portforward.go b/contrib/mounts-virtualworkspace/utils/portforward/portforward.go new file mode 100644 index 00000000000..9874727cd1e --- /dev/null +++ b/contrib/mounts-virtualworkspace/utils/portforward/portforward.go @@ -0,0 +1,47 @@ +package portforward + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +import ( + "context" + "fmt" + "net" + "net/http" + + corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/rest" +) + +// DialContext returns a connection to the specified cluster/namespace/pod/port. +func DialContext(ctx context.Context, restconfig *rest.Config, namespace, pod, port string) (net.Conn, error) { + spdyConn, err := dialSpdy(ctx, restconfig, "/api/v1/namespaces/"+namespace+"/pods/"+pod+"/portforward") + if err != nil { + return nil, fmt.Errorf("failed to dial spdy: %w", err) + } + + // Connect the error stream, r/o + errorStream, err := spdyConn.CreateStream(http.Header{ + corev1.StreamType: []string{corev1.StreamTypeError}, + corev1.PortHeader: []string{port}, + corev1.PortForwardRequestIDHeader: []string{"0"}, + }) + if err != nil { + spdyConn.Close() + return nil, fmt.Errorf("failed to create error stream: %w", err) + } + errorStream.Close() // this actually means CloseWrite() + + // Connect the data stream, r/w + dataStream, err := spdyConn.CreateStream(http.Header{ + corev1.StreamType: []string{corev1.StreamTypeData}, + corev1.PortHeader: []string{port}, + corev1.PortForwardRequestIDHeader: []string{"0"}, + }) + if err != nil { + spdyConn.Close() + return nil, fmt.Errorf("failed to create data stream: %w", err) + } + + return NewStreamConn(spdyConn, dataStream, errorStream), nil +} diff --git a/contrib/mounts-virtualworkspace/utils/portforward/streamconn.go b/contrib/mounts-virtualworkspace/utils/portforward/streamconn.go new file mode 100644 index 00000000000..df00d1639a3 --- /dev/null +++ b/contrib/mounts-virtualworkspace/utils/portforward/streamconn.go @@ -0,0 +1,79 @@ +package portforward + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +import ( + "errors" + "io" + "net" + "time" + + "k8s.io/apimachinery/pkg/util/httpstream" +) + +type addr struct{} + +func (addr) Network() string { return "streamconn" } +func (addr) String() string { return "streamconn" } + +// streamConn wraps a pair of SPDY streams and pretends to be a net.Conn +type streamConn struct { + c httpstream.Connection + dataStream httpstream.Stream + errorStream httpstream.Stream + errch chan error +} + +var _ net.Conn = (*streamConn)(nil) + +func NewStreamConn(c httpstream.Connection, dataStream, errorStream httpstream.Stream) net.Conn { + s := &streamConn{ + errch: make(chan error, 1), + c: c, + dataStream: dataStream, + errorStream: errorStream, + } + + go s.readErrorStream() + + return s +} + +func (s *streamConn) readErrorStream() { + message, err := io.ReadAll(s.errorStream) + if err != nil { + s.errch <- err + } else if len(message) > 0 { + s.errch <- errors.New(string(message)) + } else { + s.errch <- nil + } + close(s.errch) +} + +func (s *streamConn) Read(b []byte) (int, error) { + n, err := s.dataStream.Read(b) + if err == io.EOF { + err = <-s.errch + if err == nil { + err = io.EOF + } + } + + return n, err +} + +func (s *streamConn) Write(b []byte) (int, error) { + return s.dataStream.Write(b) +} + +func (s *streamConn) Close() error { + return s.c.Close() +} + +func (s *streamConn) LocalAddr() net.Addr { return &addr{} } +func (s *streamConn) RemoteAddr() net.Addr { return &addr{} } +func (s *streamConn) SetDeadline(time.Time) error { return errors.New("not implemented") } +func (s *streamConn) SetReadDeadline(time.Time) error { return errors.New("not implemented") } +func (s *streamConn) SetWriteDeadline(time.Time) error { return errors.New("not implemented") } diff --git a/contrib/mounts-virtualworkspace/utils/secrets/secrets.go b/contrib/mounts-virtualworkspace/utils/secrets/secrets.go new file mode 100644 index 00000000000..4e5aca98220 --- /dev/null +++ b/contrib/mounts-virtualworkspace/utils/secrets/secrets.go @@ -0,0 +1,21 @@ +package secrets + +import ( + "crypto/rand" + "encoding/base64" + "fmt" +) + +// GenerateSecret generates a random string of specified length. +func GenerateSecret(length int) (string, error) { + // Allocate a byte slice for the random bytes + bytes := make([]byte, length) + + // Read random bytes into the slice + if _, err := rand.Read(bytes); err != nil { + return "", fmt.Errorf("failed to generate random bytes: %w", err) + } + + // Encode the bytes to a base64 string to make it printable + return base64.URLEncoding.EncodeToString(bytes)[:length], nil +} diff --git a/contrib/mounts-virtualworkspace/virtual/context/keys.go b/contrib/mounts-virtualworkspace/virtual/context/keys.go new file mode 100644 index 00000000000..133a7c6daec --- /dev/null +++ b/contrib/mounts-virtualworkspace/virtual/context/keys.go @@ -0,0 +1,44 @@ +/* +Copyright 2023 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 context + +import ( + "context" + "errors" +) + +// proxyTargetNameContextKeyType is the type of the key for the request context value +// that will carry the name of the Proxy resources with be proxied with. +type proxyTargetNameContextKeyType string + +// proxyTargetKeyContextKey is the key for the request context value +// that will carry the name of the SyncTarget resources with be synced with. +const proxyTargetKeyContextKey proxyTargetNameContextKeyType = "ProxyAgentVirtualWorkspaceProxyTargetKey" + +// WithProxyTargetKey adds a Proxy key to the context. +func WithProxyTargetKey(ctx context.Context, syncTargetKey string) context.Context { + return context.WithValue(ctx, proxyTargetKeyContextKey, syncTargetKey) +} + +// ProxyTargetKeyFrom retrieves the Proxy name key from the context, if any. +func ProxyTargetKeyFrom(ctx context.Context) (string, error) { + stk, hasProxyTargetKey := ctx.Value(proxyTargetKeyContextKey).(string) + if !hasProxyTargetKey { + return "", errors.New("context must contain a valid non-empty Proxy key") + } + return stk, nil +} diff --git a/contrib/mounts-virtualworkspace/virtual/options/options.go b/contrib/mounts-virtualworkspace/virtual/options/options.go new file mode 100644 index 00000000000..5cba9b71cc5 --- /dev/null +++ b/contrib/mounts-virtualworkspace/virtual/options/options.go @@ -0,0 +1,71 @@ +/* +Copyright 2023 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 ( + "github.com/kcp-dev/kcp/pkg/virtual/framework/rootapiserver" + "github.com/kcp-dev/kcp/pkg/virtual/options" + "github.com/spf13/pflag" + + "k8s.io/client-go/rest" + + proxyinformers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" + proxyoptions "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/virtual/proxy/options" +) + +const virtualWorkspacesFlagPrefix = "virtual-workspaces-" + +type Options struct { + Proxy *proxyoptions.Proxy +} + +func NewOptions() *Options { + return &Options{ + Proxy: proxyoptions.New(), + } +} + +func (o *Options) Validate() []error { + var errs []error + + errs = append(errs, o.Proxy.Validate(virtualWorkspacesFlagPrefix)...) + + return errs +} + +func (o *Options) AddFlags(fs *pflag.FlagSet) { + o.Proxy.AddFlags(fs, virtualWorkspacesFlagPrefix) +} + +func (o *Options) NewVirtualWorkspaces( + rootPathPrefix string, + config *rest.Config, + cachedProxyInformers proxyinformers.SharedInformerFactory, + store state.ClientSetStoreInterface, +) ([]rootapiserver.NamedVirtualWorkspace, error) { + proxy, err := o.Proxy.NewVirtualWorkspaces(rootPathPrefix, config, cachedProxyInformers, store) + if err != nil { + return nil, err + } + + all, err := options.Merge(proxy) + if err != nil { + return nil, err + } + return all, nil +} diff --git a/contrib/mounts-virtualworkspace/virtual/proxy/builder/build.go b/contrib/mounts-virtualworkspace/virtual/proxy/builder/build.go new file mode 100644 index 00000000000..a1634acb76f --- /dev/null +++ b/contrib/mounts-virtualworkspace/virtual/proxy/builder/build.go @@ -0,0 +1,74 @@ +/* +Copyright 2023 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 ( + "strings" + + kcpdynamic "github.com/kcp-dev/client-go/dynamic" + kcpkubernetesclientset "github.com/kcp-dev/client-go/kubernetes" + "github.com/kcp-dev/kcp/pkg/virtual/framework/rootapiserver" + + proxyinformers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" +) + +const ( + // ProxyVirtualWorkspaceName holds the name of the virtual workspace for the proxy where we + // expect traffic to be routed to. + ProxyVirtualWorkspaceName string = "cluster-proxy" + // EdgeProxyVirtualWorkspaceName holds the name of the virtual workspace for the edge proxy + // connections. This is used for the edge clusters to connect & register to the cluster proxy. + //EdgeProxyVirtualWorkspaceName string = "edge-proxy" + //EdgeTunnelSuffix string = "proxy" + ProxyTunnelSuffix string = "proxy" +) + +// BuildVirtualWorkspace builds two virtual workspaces, ProxyVirtualWorkspaceName by instantiating a DynamicVirtualWorkspace which, +// combined with a ForwardingREST REST storage implementation, serves a ProxyAPI list maintained by the APIReconciler controller. +func BuildVirtualWorkspace( + rootPathPrefix string, + kubeClusterClient kcpkubernetesclientset.ClusterInterface, + dynamicClusterClient kcpdynamic.ClusterInterface, + cachedProxyInformers proxyinformers.SharedInformerFactory, + store state.ClientSetStoreInterface, +) []rootapiserver.NamedVirtualWorkspace { + if !strings.HasSuffix(rootPathPrefix, "/") { + rootPathPrefix += "/" + } + + proxyProvider := clusterProxyProvider{ + kubeClusterClient: kubeClusterClient, + dynamicClusterClient: dynamicClusterClient, + cachedProxyInformers: cachedProxyInformers, + rootPathPrefix: rootPathPrefix, + state: store, + } + + builder := proxyProvider.newTemplate( + clusterParameters{ + virtualWorkspaceName: ProxyVirtualWorkspaceName, + }, store) + + return []rootapiserver.NamedVirtualWorkspace{ + { + Name: ProxyVirtualWorkspaceName, + VirtualWorkspace: builder.buildClusterProxyVirtualWorkspace(), + }, + } + +} diff --git a/contrib/mounts-virtualworkspace/virtual/proxy/builder/cluster_proxy.go b/contrib/mounts-virtualworkspace/virtual/proxy/builder/cluster_proxy.go new file mode 100644 index 00000000000..1b0516b87b2 --- /dev/null +++ b/contrib/mounts-virtualworkspace/virtual/proxy/builder/cluster_proxy.go @@ -0,0 +1,93 @@ +package builder + +import ( + "context" + "fmt" + "path" + "strings" + + kcpcache "github.com/kcp-dev/apimachinery/v2/pkg/cache" + "github.com/kcp-dev/kcp/pkg/authorization/delegated" + dynamiccontext "github.com/kcp-dev/kcp/pkg/virtual/framework/dynamic/context" + "github.com/kcp-dev/logicalcluster/v3" + + "k8s.io/apiserver/pkg/authorization/authorizer" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" + + mountsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/mounts/v1alpha1" +) + +func (p *clusterProxy) authorizeCluster(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) { + proxyKey := dynamiccontext.APIDomainKeyFrom(ctx) + negotiationWorkspaceName, _, proxyName, err := kcpcache.SplitMetaClusterNamespaceKey(string(proxyKey)) + if err != nil { + return authorizer.DecisionNoOpinion, "", err + } + + authz, err := delegated.NewDelegatedAuthorizer(negotiationWorkspaceName, p.kubeClusterClient, delegated.Options{}) + if err != nil { + return authorizer.DecisionNoOpinion, "Error", err + } + + SARAttributes := authorizer.AttributesRecord{ + User: a.GetUser(), + Verb: "proxy", + Name: proxyName, + APIGroup: mountsv1alpha1.SchemeGroupVersion.Group, + APIVersion: mountsv1alpha1.SchemeGroupVersion.Version, + Resource: "clusters", + ResourceRequest: true, + } + + return authz.Authorize(ctx, SARAttributes) +} + +func (p *clusterProxy) resolveClusterProxyRootPath(urlPath string, requestContext context.Context) (accepted bool, prefixToStrip string, completedContext context.Context) { + select { + case <-p.readyClusterCh: + default: + // If the cluster is not ready, we should not accept any requests + fmt.Println("VirtualWorkspace is not ready") + return + } + + rootPathPrefix := p.rootPathPrefix + p.clusterParameters.virtualWorkspaceName + "/" + + completedContext = requestContext + if !strings.HasPrefix(urlPath, rootPathPrefix) { + return + } + withoutRootPathPrefix := strings.TrimPrefix(urlPath, rootPathPrefix) + + // Incoming requests to this virtual workspace will look like: + // /services/cluster-proxy/root:org:ws/apis/targets.contrib.kcp.io/v1alpha1/kubeclusters//core/v1/namespaces//pods//exec + // └───────────┐ + // Where the withoutRootPathPrefix starts here: ┘ + parts := strings.SplitN(withoutRootPathPrefix, "/", 7) + if len(parts) < 3 || parts[0] == "" || parts[1] == "" || parts[2] == "" { + return + } + clusterPath := logicalcluster.NewPath(parts[0]) + proxyName := parts[5] + + clusterName, ok := clusterPath.Name() + if !ok { + return + } + + // TODO: verify proxy exists here + apiDomainKey := dynamiccontext.APIDomainKey(kcpcache.ToClusterAwareKey(clusterName.String(), "", proxyName)) + + // /services/cluster-proxy//targets.contrib.kcp.io/v1alpha1/kubeclusters//core/v1/namespaces//pods//exec + // ┌──────────────────────────────────────────────────────────────────────────────────┘ + // We are now here: ┘ + + completedContext = dynamiccontext.WithAPIDomainKey(completedContext, apiDomainKey) + completedContext = genericapirequest.WithCluster(completedContext, genericapirequest.Cluster{ + Name: clusterName, + }) + + prefixToStrip = path.Join(rootPathPrefix, parts[0]) + accepted = true + return +} diff --git a/contrib/mounts-virtualworkspace/virtual/proxy/builder/proxy.go b/contrib/mounts-virtualworkspace/virtual/proxy/builder/proxy.go new file mode 100644 index 00000000000..0b7dd653aba --- /dev/null +++ b/contrib/mounts-virtualworkspace/virtual/proxy/builder/proxy.go @@ -0,0 +1,268 @@ +/* +Copyright 2023 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" + "errors" + "fmt" + "log" + "net" + "net/http" + "net/http/httputil" + "net/url" + "strings" + "sync" + + kcpdynamic "github.com/kcp-dev/client-go/dynamic" + kcpkubernetesclientset "github.com/kcp-dev/client-go/kubernetes" + "github.com/kcp-dev/kcp/pkg/virtual/framework" + "github.com/kcp-dev/kcp/pkg/virtual/framework/handler" + "github.com/kcp-dev/logicalcluster/v3" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apiserver/pkg/authorization/authorizer" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" + genericapiserver "k8s.io/apiserver/pkg/server" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + + targetsv1alpha1 "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/apis/targets/v1alpha1" + mountsinformers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/utils/portforward" +) + +type clusterProxyProvider struct { + kubeClusterClient kcpkubernetesclientset.ClusterInterface + dynamicClusterClient kcpdynamic.ClusterInterface + cachedProxyInformers mountsinformers.SharedInformerFactory + rootPathPrefix string + state state.ClientSetStoreInterface +} + +type clusterParameters struct { + virtualWorkspaceName string +} + +func (c *clusterProxyProvider) newTemplate(clusterParameters clusterParameters, store state.ClientSetStoreInterface) *clusterProxy { + return &clusterProxy{ + clusterProxyProvider: *c, + clusterParameters: clusterParameters, + readyClusterCh: make(chan struct{}), + store: store, + } +} + +type controlMsg struct { + Command string `json:"command,omitempty"` // "keep-alive", "conn-ready", "pickup-failed" + ConnPath string `json:"connPath,omitempty"` // conn pick-up URL path for "conn-url", "pickup-failed" + Err string `json:"err,omitempty"` +} + +type key struct { + clusterName logicalcluster.Name + proxyName string +} + +type clusterProxy struct { + clusterProxyProvider + + clusterParameters + + readyClusterCh chan struct{} + + // Proxy dialer pool + mu sync.Mutex + store state.ClientSetStoreInterface +} + +func (p *clusterProxy) readyCluster() error { + select { + case <-p.readyClusterCh: + return nil + default: + return errors.New("proxy virtual workspace controllers are not started") + } +} + +func (p *clusterProxy) buildClusterProxyVirtualWorkspace() *handler.VirtualWorkspace { + defer close(p.readyClusterCh) + return &handler.VirtualWorkspace{ + RootPathResolver: framework.RootPathResolverFunc(p.resolveClusterProxyRootPath), + Authorizer: authorizer.AuthorizerFunc(p.authorizeCluster), + ReadyChecker: framework.ReadyFunc(p.readyCluster), + HandlerFactory: handler.HandlerFactory(func(rootAPIServerConfig genericapiserver.CompletedConfig) (http.Handler, error) { + return http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + // logger := klog.FromContext(ctx) + + ri, exists := genericapirequest.RequestInfoFrom(ctx) + if !exists { + http.Error(w, "could not determine resource", http.StatusInternalServerError) + return + } + + // proxy vcluster (goes to same cluster but with vcluster inside namespace) + + // proxy kubecluster (goes to full cluster) + + switch ri.Resource { + case "kubeclusters": + p.proxyKubeCluster(ri, w, r) + case "vclusters": + p.proxyVCluster(ri, w, r) + default: + http.Error(w, "could not determine resource - unknown provider", http.StatusInternalServerError) + } + }), nil + }), + } +} + +func (p *clusterProxy) proxyKubeCluster(ri *genericapirequest.RequestInfo, w http.ResponseWriter, r *http.Request) { + if !ri.IsResourceRequest || + ri.Resource != "kubeclusters" || + ri.Subresource != "proxy" || + ri.APIGroup != targetsv1alpha1.SchemeGroupVersion.Group || + ri.APIVersion != targetsv1alpha1.SchemeGroupVersion.Version || + ri.Name == "" { + http.Error(w, "could not determine resource", http.StatusInternalServerError) + return + } + + // Get secrets from url and strip it away: + // https://localhost:6444/services/cluster-proxy/1t1mlh6tgdzuelpg/apis/targets.contrib.kcp.io/v1alpha1/kubeclusters/proxy-cluster/proxy/secret/cFI-tl0Qvwqnln4N + // ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + // We are now here: ┘ + parts := strings.SplitN(r.URL.Path, "/", 8) + secrets := strings.TrimPrefix(parts[7], "secret/") + parts = strings.SplitN(secrets, "/", 2) + + value, found := p.store.Get(state.KindKubeClusters, parts[0]) + if !found { + http.Error(w, "Unauthorized", http.StatusInternalServerError) + return + } + + // Parse the API server URL from the config + apiServerURL, err := url.Parse(value.Config.Host) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // Create a reverse proxy that targets the Kubernetes API server + proxy := httputil.NewSingleHostReverseProxy(apiServerURL) + transport, err := rest.TransportFor(value.Config) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + proxy.Transport = transport + + r.URL.Path = parts[1] + proxy.ServeHTTP(w, r) +} + +func (p *clusterProxy) proxyVCluster(ri *genericapirequest.RequestInfo, w http.ResponseWriter, r *http.Request) { + if !ri.IsResourceRequest || + ri.Resource != "vclusters" || + ri.Subresource != "proxy" || + ri.APIGroup != targetsv1alpha1.SchemeGroupVersion.Group || + ri.APIVersion != targetsv1alpha1.SchemeGroupVersion.Version || + ri.Name == "" { + http.Error(w, "could not determine resource", http.StatusInternalServerError) + return + } + + // Get secrets from url and strip it away: + // https://localhost:6444/services/cluster-proxy/1t1mlh6tgdzuelpg/apis/targets.contrib.kcp.io/v1alpha1/vclusters/proxy-cluster/proxy/secret/cFI-tl0Qvwqnln4N + // + // ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + // + // We are now here: ┘ + parts := strings.SplitN(r.URL.Path, "/", 8) + secrets := strings.TrimPrefix(parts[7], "secret/") + parts = strings.SplitN(secrets, "/", 2) + + value, found := p.store.Get(state.KindVClusters, parts[0]) + if !found { + http.Error(w, "Unauthorized", http.StatusInternalServerError) + return + } + + // Parse the API server URL from the config + apiServerURL, err := url.Parse(value.Config.Host) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // Define port-forward parameters + serviceName := "vcluster" // Name of the service hardcoded in provisioner. + + // Find a pod that matches the service's selector + podName, err := findPodForService(value.Client, value.VClusterNamespace, serviceName) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + tlsConfig, err := rest.TLSConfigFor(value.VClusterConfig) + if err != nil { + log.Fatalf("Failed to convert TLSClientConfig: %v", err) + } + + transport := &http.Transport{ + DialContext: func(ctx context.Context, network, address string) (net.Conn, error) { + return portforward.DialContext(ctx, value.Config, value.VClusterNamespace, podName, "6443") + }, + TLSClientConfig: tlsConfig, + } + + // Create a reverse proxy that targets the Kubernetes API server + proxy := httputil.NewSingleHostReverseProxy(apiServerURL) + proxy.Transport = transport + + r.URL.Path = parts[1] + proxy.ServeHTTP(w, r) +} + +// findPodForService finds a pod that matches the service's selectors +func findPodForService(clientset *kubernetes.Clientset, namespace string, serviceName string) (string, error) { + service, err := clientset.CoreV1().Services(namespace).Get(context.TODO(), serviceName, metav1.GetOptions{}) + if err != nil { + return "", fmt.Errorf("failed to get service: %w", err) + } + + // Get the label selector for the service + labelSelector := metav1.FormatLabelSelector(&metav1.LabelSelector{MatchLabels: service.Spec.Selector}) + pods, err := clientset.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{ + LabelSelector: labelSelector, + }) + if err != nil { + return "", fmt.Errorf("failed to list pods: %w", err) + } + if len(pods.Items) == 0 { + return "", fmt.Errorf("no pods found for service %s", serviceName) + } + + // Return the name of the first pod found + return pods.Items[0].Name, nil +} diff --git a/contrib/mounts-virtualworkspace/virtual/proxy/doc.go b/contrib/mounts-virtualworkspace/virtual/proxy/doc.go new file mode 100644 index 00000000000..7ae8f9aa9fd --- /dev/null +++ b/contrib/mounts-virtualworkspace/virtual/proxy/doc.go @@ -0,0 +1,26 @@ +/* +Copyright 2023 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 proxy and its sub-packages provide the Proxy Virtual Workspace. +// +// It exposes an APIserver URL for each Proxy hosting a proxy agent, +// with REST endpoints for APIs that have been imported from this Cluster proxy and published. +// +// It combines and integrates: +// +// The builder package is the place where all these components are combined together, especially in the +// BuildVirtualWorkspace() function. +package proxy diff --git a/contrib/mounts-virtualworkspace/virtual/proxy/options/options.go b/contrib/mounts-virtualworkspace/virtual/proxy/options/options.go new file mode 100644 index 00000000000..0782f98e348 --- /dev/null +++ b/contrib/mounts-virtualworkspace/virtual/proxy/options/options.go @@ -0,0 +1,73 @@ +/* +Copyright 2023 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 ( + kcpdynamic "github.com/kcp-dev/client-go/dynamic" + kcpkubernetesclientset "github.com/kcp-dev/client-go/kubernetes" + "github.com/kcp-dev/kcp/pkg/virtual/framework/rootapiserver" + "github.com/spf13/pflag" + + "k8s.io/client-go/rest" + + proxyinformers "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/client/informers/externalversions" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/state" + "github.com/kcp-dev/kcp/contrib/mounts-virtualworkspace/virtual/proxy/builder" +) + +type Proxy struct { + VirtualWorkspaceHostname string +} + +func New() *Proxy { + return &Proxy{} +} + +func (o *Proxy) AddFlags(flags *pflag.FlagSet, prefix string) { + if o == nil { + return + } + flags.StringVar(&o.VirtualWorkspaceHostname, prefix+"proxy-hostname", o.VirtualWorkspaceHostname, "The proxy virtual workspace hostname.") +} + +func (o *Proxy) Validate(flagPrefix string) []error { + if o == nil { + return nil + } + errs := []error{} + + return errs +} + +func (o *Proxy) NewVirtualWorkspaces( + rootPathPrefix string, + config *rest.Config, + cachedProxyInformers proxyinformers.SharedInformerFactory, + store state.ClientSetStoreInterface, +) (workspaces []rootapiserver.NamedVirtualWorkspace, err error) { + config = rest.AddUserAgent(rest.CopyConfig(config), "proxy-virtual-workspace") + kubeClusterClient, err := kcpkubernetesclientset.NewForConfig(config) + if err != nil { + return nil, err + } + dynamicClusterClient, err := kcpdynamic.NewForConfig(config) + if err != nil { + return nil, err + } + + return builder.BuildVirtualWorkspace(rootPathPrefix, kubeClusterClient, dynamicClusterClient, cachedProxyInformers, store), nil +} diff --git a/go.mod b/go.mod index e2598a9887a..08f4e18e988 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.22.0 require ( github.com/abiosoft/lineprefix v0.1.4 + github.com/aojea/rwconn v0.1.1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc github.com/egymgmbh/go-prefix-writer v0.0.0-20180609083313-7326ea162eca github.com/emicklei/go-restful/v3 v3.11.0 diff --git a/go.sum b/go.sum index 6f88281c037..f9a07d716c6 100644 --- a/go.sum +++ b/go.sum @@ -14,6 +14,8 @@ github.com/abiosoft/lineprefix v0.1.4/go.mod h1:Myq9hfXs8e2OmHFvajp3pHxxThZL645X github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= +github.com/aojea/rwconn v0.1.1 h1:vsYyhoQghQ5HH98QE+xmNwnKsTm8GxWjpvxGft6s7q8= +github.com/aojea/rwconn v0.1.1/go.mod h1:LUO0QX1YNsA51BR48slR87GsvEMiTTOWNdC6aoG+BTA= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= diff --git a/kubeconfig b/kubeconfig new file mode 100644 index 00000000000..006e6ae1430 --- /dev/null +++ b/kubeconfig @@ -0,0 +1,20 @@ +apiVersion: v1 +clusters: +- cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCVENDQWUyZ0F3SUJBZ0lJTzk4UDBQMWxQZHN3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TkRFd01qWXhOek00TVRsYUZ3MHpOREV3TWpReE56UXpNVGxhTUJVeApFekFSQmdOVkJBTVRDbXQxWW1WeWJtVjBaWE13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLCkFvSUJBUUMwSzhxUzFnK1A0T0RPTkhTWjdlNVhxWnRLOE11QUZIa2p3eUNiaWtMWDJBMUxOalFZdkhGaXA1MDgKTkw5QXZLNGdzNTF0Q3g0WldWckovemU2c01rZjE2MTRYSWtsTnc2RU1DZDYyamdKYkFHeGdnWFFqZGVxcjRnSAo2clI3Z0RtR3BNOGNXVXhBWFdaUXZ0TVl4UGIyWlZXT2tRWngxMy9vZlUwa2VRQ0RDRlJ4QjdIS1VMUS9vNDNlCkZGWjdTRjJreDhHdlhFMVo1ZTRtbG9vcE5HQ0lQQlh5b2JRR0ViQk4zdjdqOUo2QlM5VmI3ZitxQmZZb2R4cXMKdmU0VUUxcS9aRS9Od0NOQlVwWUdzRDIwbmpxREkyT3J1ODJwWTNwQXRBUzc3Vko0ZVo5aVpqK0N6ZlRKZ0wxTQp2ZWM5N1lNMi9lVEUwMnhXd01WV0ZlMFlEamtYQWdNQkFBR2pXVEJYTUE0R0ExVWREd0VCL3dRRUF3SUNwREFQCkJnTlZIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJTMzVGT0plMis2a2RQU1YrQVpYeWRZQmVsNEh6QVYKQmdOVkhSRUVEakFNZ2dwcmRXSmxjbTVsZEdWek1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ25uSmpuaDgzSAo5N0V6S0dIakJrQW9QYzBTd2hzM0Zqay9JTk5pT2t1TkovdmdzRHQyNXJkL20xZnRYSkpEZzJYZTFsdktlcGJFClo4RnpPN0I5SmFyUE9vZng0cmdqQ08xRmJnOHV4ZWhJSWNwWjZTR1NER1lWSFU1QTFTMVdqY1JndzEwaWhwSDgKNDRrQ0hZMktvVDBsRmhaaStLMHkxL2pLVzJQT0lvUUdFckMyWnZOWWNYa2xpQ1hralpLdjkwYjN2R1hoczlLVQo3ZHY0ZmRDNlQwQTBqeTV6Um1TVzNCaC9UVXcvZ3FpS1R5NjVaNVFWdC9lQzdiMTdoc2hWZlFtWnhLUjQrUS9XCmxLV0p2dEFNek1FVTdYY0FIa3diNEtMZFlOSHhRdGhyNnpPVFFKRmp5R1RoRS9zbHphZldCbzZBL01XM1UvVFIKbjFHVDZmZlpSdm5PCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:44135 + name: kind-kind +contexts: +- context: + cluster: kind-kind + user: kind-kind + name: kind-kind +current-context: kind-kind +kind: Config +preferences: {} +users: +- name: kind-kind + user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURLVENDQWhHZ0F3SUJBZ0lJWVE0MXc4UHV2dnd3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TkRFd01qWXhOek00TVRsYUZ3MHlOVEV3TWpZeE56UXpNakZhTUR3eApIekFkQmdOVkJBb1RGbXQxWW1WaFpHMDZZMngxYzNSbGNpMWhaRzFwYm5NeEdUQVhCZ05WQkFNVEVHdDFZbVZ5CmJtVjBaWE10WVdSdGFXNHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEa1dhRVAKSkVURnNLamdWcnkxbjE5UlU2RUprcUp2L09JQ1ZKeng0TlBxNy9VdElPSUZ2VzdQa2JOZi9jcUZqWXo5OXlTVApqMGUvK0p2WFg4aWZveGtzZjhUbnovdjdlNkpzVU9XMGFCVnFaZldFaHpScHo3NndoNVQyMU50cytHQ2R1VzhlCmZWYW55RXdNQlgwR3hmZzcxNWdhVVFmb3VJOExmZTlZdU8xSmFvZ0JDU3NRNlNQbG4rbzhsZWV6dW9EMkZUcC8KaHo5TFVjeEdrRUYvbHZEZkNTRitIaGlma3pOb0d3ci9YSy9WZmVVQmdrK1VZZnZFR3pneWozVEVpWmZzTVRadQp1RDEyK0hzdllMamlhcGtNRFFxZEZRM0VSVjNsVHBpR21paklPUVRKYW5VdWVNbFlKbFNxZXNsbzB0Yit3ZWpiCnhRNU5mSUVTMjQ3S3poU1JBZ01CQUFHalZqQlVNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUsKQmdnckJnRUZCUWNEQWpBTUJnTlZIUk1CQWY4RUFqQUFNQjhHQTFVZEl3UVlNQmFBRkxma1U0bDdiN3FSMDlKWAo0QmxmSjFnRjZYZ2ZNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUIxY2VYdzRYOHhCdUJoTnpPeG9qRVV3SjZxCkJ3ZGJtTFlocDRIQW14VzNTUTlqVDVLU3BqbzZpWjkvcXlvYVo1RUJWWlJ3M09HY2xSM0x5VjRBZkdRR2NweDAKbC9sdjdZZVB3OG1lTVFiZzJMTVhjY3dudS8ycC9DU1RkWHBoRHg2bU1Bblo1NmMwajkrNUcyenBoZzJkQ001bAp2b1cwZ0VWSU1BVFF4WWdqYzUxTGt5VzB1T3hoWnNySkJMSXR5SEllNisrckx1RmdwbUEvQjRISmlzVWdUQ2NRClVFZ0dLWXhwMEdtTHh4cjc3L2JsaHlkWFlEM0dBeGdXNzlSdHRmcE9UZi9uZU9aUDNKVDVOMTJjNmdvc3E2MlcKYVF0Q2ZYK2EvMkJFcU00ZDg4RStYRDgrMnFkenhhZ2VuMVQyQTIzbHBxUVFHNmI1TEwvRnErUTdwTW1oCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBNUZtaER5UkV4YkNvNEZhOHRaOWZVVk9oQ1pLaWIvemlBbFNjOGVEVDZ1LzFMU0RpCkJiMXV6NUd6WC8zS2hZMk0vZmNrazQ5SHYvaWIxMS9JbjZNWkxIL0U1OC83KzN1aWJGRGx0R2dWYW1YMWhJYzAKYWMrK3NJZVU5dFRiYlBoZ25ibHZIbjFXcDhoTURBVjlCc1g0TzllWUdsRUg2TGlQQzMzdldManRTV3FJQVFrcgpFT2tqNVovcVBKWG5zN3FBOWhVNmY0Yy9TMUhNUnBCQmY1Ynczd2toZmg0WW41TXphQnNLLzF5djFYM2xBWUpQCmxHSDd4QnM0TW85MHhJbVg3REUyYnJnOWR2aDdMMkM0NG1xWkRBMEtuUlVOeEVWZDVVNllocG9veURrRXlXcDEKTG5qSldDWlVxbnJKYU5MVy9zSG8yOFVPVFh5QkV0dU95czRVa1FJREFRQUJBb0lCQUJtM3NuajNGN3ZBRXJUNQpiOVZ3dHBaOU9iVFBTL1lhNEFWdExDUGRzMkJSV0NhVi9uNnhBQXJtbVBJbHJpcHViOE9ta3ZyL2R4QTYycXBlCkFrVmdaQlJyNjJ4RU0xZjJhNnVSVE4yTm4yUFZTZHA4TTczN0JMbnkreWIxZ0NUOHNEenpSbjJEbGovZFFodFUKZnVsRllKaTB4aytvY3FDV01KNFZ0K0FoSzdCSjFiYmMxbHhjejV1cytSRWFlZ3JkWGxhOXFhdWh2U29GM01aWQpyaWNCVmtFZFF1L2lPYkFjbVVQZXNCbE5yc2tISmlnN2s4M2pteGplQWQ1RkhzKzRWZHhxMFRQUjlsUjlHSU1DCkRhSTljMVdiekhPbHRMOWJjOXlRRVR2L1hUSnhybGZheVl2ZzBJTG9yNUg0SHIvT2E4aHpBVzVlbkFNR3JWaW8KcGoxa3g3VUNnWUVBNTd4NnZCVEIvTGdQckdLM05TemJXUElOTlRsMHQvOXBuaG4xR0d2NWR4QmlSbXRNeklWcgpLQTFxQjFWcFlRNGtsUlVycEJlY0JmUnR6a2pGcDlqM09DbnBlQ2lnQTRSbHU2dThTUVZ0ZUNiZU9tTklUd0t2Ckh3aCtZY285bVduRk02a2JFTTVwUDE5cEpzZEFqMGVXTW93czU3WDFtQ1hqQnRXZkcwUXgzMWNDZ1lFQS9FSmoKQ1ZyZU50OXZpenBGaDRIYzdmT1hXcFhVb0JHak01ekIyYUNXVW16MitTT2lMVk42Z2syTVNSRHZDZDlSU3pwSQpLN3M1YkN1TS9tSmlPM1pud3l1NnpWYk9jdk9yR0pRSE1aaU9GaEpuM2FybHpzY2hISDJURXRZQnQ0RXN5c3VTCnpaMzFYN3lPVnZjSzVNYWpKWlJOU0dqYVBDUSsrWlg5NHE5M2dsY0NnWUJOcWZGSVQzeWtBZHZlM2thZ1g2UXoKcnd1V0p1ZGpNd3BtbmpSeU50Mm9kYWs2Q0lQNGwwNU9ZaENDM0xFd2dkam96ZXVPVnd0SFE1LzVYcEkvcW90UQpHMXZQbFczclA5Z0lpWW5Vdnlqczk3bkt2N05nSjNvaFlHdGF3cmphVFlSMXg5cjJTdmNpOGdyL29BK1c5VnIxCkhkMSsycEN3cVNIcERIY0NZRnlHaVFLQmdRQzdXd2M1ZEg3a25IQzVKSTl0aEhzMVZCMU96MGQ3bDMzeUlIUXQKa2NMejl6QTdmRWJBaVdiTkRwR3AxdVRqSFRUQXZjbktpU1N0L1c2YnBUQzJYMHZUdmsvZ29KOTI2eGxoaU5nSwo4dlpjMkZEQ1oyS0ZnSXBNSWN3eFNqYytOcmV3NngvZWpYb29IK0JNSVBHN1Z2am5PVTFwQVU5TktkS0lCdW5wCkNrK2x3d0tCZ1FDREdaWmJuTXc4Y00rc1ZsWHVxWVRkMzFtbGxuT3B5WUlwaTJxbldmUzBMS09lSVdWNkdrby8KOGFHKzVWczc2cWIrNmR3NHVtUWhCbEJza0EydzhMdXdIUFNrOXBUdHJYOGs5S2R5Mk1MK0YxRDdRbVJRbjJXOApzNW9FRHQ2T0J6cEhQUC9xelluMUViNTVPcng0dzNPRFAyOG9yZHFSWmhueFdIZFVXTHZWYmc9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= + diff --git a/pkg/index/index.go b/pkg/index/index.go index 19a994dbccb..9f9c4b1a4e9 100644 --- a/pkg/index/index.go +++ b/pkg/index/index.go @@ -88,9 +88,6 @@ type State struct { } func (c *State) UpsertWorkspace(shard string, ws *tenancyv1alpha1.Workspace) { - if ws.Status.Phase == corev1alpha1.LogicalClusterPhaseScheduling { - return - } clusterName := logicalcluster.From(ws) diff --git a/pkg/server/localproxy.go b/pkg/server/localproxy.go index 8a6fe9b65bd..dd214275a4d 100644 --- a/pkg/server/localproxy.go +++ b/pkg/server/localproxy.go @@ -213,7 +213,7 @@ func WithLocalProxy( // NewLocalProxyHandler returns a handler with a local-only mini-front-proxy. // This function is very similar to proxy/mapping.go.NewHandler. // If we want to re-use that code, we basically would be merging proxy with server packages. -// Which is not desirable at the point of writing (2024.10-26), but might be in the future. +// Which is not desirable at the point of writing (2024-10-26), but might be in the future. func NewLocalProxyHandler(defaultHandler http.Handler, index index.Index, additionalMappingsFile string) (http.Handler, error) { mapping := []proxy.PathMapping{} if additionalMappingsFile != "" { @@ -222,7 +222,6 @@ func NewLocalProxyHandler(defaultHandler http.Handler, index index.Index, additi return nil, fmt.Errorf("failed to read mapping file %q: %w", additionalMappingsFile, err) } - var mapping []proxy.PathMapping if err = yaml.Unmarshal(mappingData, &mapping); err != nil { return nil, fmt.Errorf("failed to unmarshal mapping file %q: %w", additionalMappingsFile, err) } diff --git a/pkg/virtual/framework/rootapiserver/server.go b/pkg/virtual/framework/rootapiserver/server.go index a291a72095f..1b63b30c31c 100644 --- a/pkg/virtual/framework/rootapiserver/server.go +++ b/pkg/virtual/framework/rootapiserver/server.go @@ -99,7 +99,6 @@ func getRootHandlerChain(c CompletedConfig, delegateAPIServer genericapiserver.D warning.AddWarning(requestContext, "", fmt.Sprintf("You are using an old kubectl-kcp plugin. Please update to a version matching the kcp server version %q.", componentbaseversion.Get().GitVersion)) } - for _, vw := range c.Extra.VirtualWorkspaces { if accepted, prefixToStrip, completedContext := vw.ResolveRootPath(req.URL.Path, requestContext); accepted { req.URL.Path = strings.TrimPrefix(req.URL.Path, prefixToStrip)