mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-03 01:06:27 +00:00
Introduce kuberc as new flag to customize defaulting and define aliases in kubectl (#125230)
This commit is contained in:
parent
3d342e9b74
commit
c7a90b670c
236
pkg/generated/openapi/zz_generated.openapi.go
generated
236
pkg/generated/openapi/zz_generated.openapi.go
generated
@ -1241,6 +1241,10 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
|
|||||||
"k8s.io/kube-scheduler/config/v1.ScoringStrategy": schema_k8sio_kube_scheduler_config_v1_ScoringStrategy(ref),
|
"k8s.io/kube-scheduler/config/v1.ScoringStrategy": schema_k8sio_kube_scheduler_config_v1_ScoringStrategy(ref),
|
||||||
"k8s.io/kube-scheduler/config/v1.UtilizationShapePoint": schema_k8sio_kube_scheduler_config_v1_UtilizationShapePoint(ref),
|
"k8s.io/kube-scheduler/config/v1.UtilizationShapePoint": schema_k8sio_kube_scheduler_config_v1_UtilizationShapePoint(ref),
|
||||||
"k8s.io/kube-scheduler/config/v1.VolumeBindingArgs": schema_k8sio_kube_scheduler_config_v1_VolumeBindingArgs(ref),
|
"k8s.io/kube-scheduler/config/v1.VolumeBindingArgs": schema_k8sio_kube_scheduler_config_v1_VolumeBindingArgs(ref),
|
||||||
|
"k8s.io/kubectl/pkg/config/v1alpha1.AliasOverride": schema_kubectl_pkg_config_v1alpha1_AliasOverride(ref),
|
||||||
|
"k8s.io/kubectl/pkg/config/v1alpha1.CommandOverride": schema_kubectl_pkg_config_v1alpha1_CommandOverride(ref),
|
||||||
|
"k8s.io/kubectl/pkg/config/v1alpha1.CommandOverrideFlag": schema_kubectl_pkg_config_v1alpha1_CommandOverrideFlag(ref),
|
||||||
|
"k8s.io/kubectl/pkg/config/v1alpha1.Preference": schema_kubectl_pkg_config_v1alpha1_Preference(ref),
|
||||||
"k8s.io/kubelet/config/v1.CredentialProvider": schema_k8sio_kubelet_config_v1_CredentialProvider(ref),
|
"k8s.io/kubelet/config/v1.CredentialProvider": schema_k8sio_kubelet_config_v1_CredentialProvider(ref),
|
||||||
"k8s.io/kubelet/config/v1.CredentialProviderConfig": schema_k8sio_kubelet_config_v1_CredentialProviderConfig(ref),
|
"k8s.io/kubelet/config/v1.CredentialProviderConfig": schema_k8sio_kubelet_config_v1_CredentialProviderConfig(ref),
|
||||||
"k8s.io/kubelet/config/v1.ExecEnvVar": schema_k8sio_kubelet_config_v1_ExecEnvVar(ref),
|
"k8s.io/kubelet/config/v1.ExecEnvVar": schema_k8sio_kubelet_config_v1_ExecEnvVar(ref),
|
||||||
@ -63549,6 +63553,238 @@ func schema_k8sio_kube_scheduler_config_v1_VolumeBindingArgs(ref common.Referenc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func schema_kubectl_pkg_config_v1alpha1_AliasOverride(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||||
|
return common.OpenAPIDefinition{
|
||||||
|
Schema: spec.Schema{
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Description: "AliasOverride stores the alias definitions.",
|
||||||
|
Type: []string{"object"},
|
||||||
|
Properties: map[string]spec.Schema{
|
||||||
|
"name": {
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Description: "Name is the name of alias that can only include alphabetical characters If the alias name conflicts with the built-in command, built-in command will be used.",
|
||||||
|
Default: "",
|
||||||
|
Type: []string{"string"},
|
||||||
|
Format: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"command": {
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Description: "Command is the single or set of commands to execute, such as \"set env\" or \"create\"",
|
||||||
|
Default: "",
|
||||||
|
Type: []string{"string"},
|
||||||
|
Format: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"prependArgs": {
|
||||||
|
VendorExtensible: spec.VendorExtensible{
|
||||||
|
Extensions: spec.Extensions{
|
||||||
|
"x-kubernetes-list-type": "atomic",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Description: "PrependArgs stores the arguments such as resource names, etc. These arguments are inserted after the alias name.",
|
||||||
|
Type: []string{"array"},
|
||||||
|
Items: &spec.SchemaOrArray{
|
||||||
|
Schema: &spec.Schema{
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Default: "",
|
||||||
|
Type: []string{"string"},
|
||||||
|
Format: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"appendArgs": {
|
||||||
|
VendorExtensible: spec.VendorExtensible{
|
||||||
|
Extensions: spec.Extensions{
|
||||||
|
"x-kubernetes-list-type": "atomic",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Description: "AppendArgs stores the arguments such as resource names, etc. These arguments are appended to the USER_ARGS.",
|
||||||
|
Type: []string{"array"},
|
||||||
|
Items: &spec.SchemaOrArray{
|
||||||
|
Schema: &spec.Schema{
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Default: "",
|
||||||
|
Type: []string{"string"},
|
||||||
|
Format: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"flags": {
|
||||||
|
VendorExtensible: spec.VendorExtensible{
|
||||||
|
Extensions: spec.Extensions{
|
||||||
|
"x-kubernetes-list-type": "atomic",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Description: "Flag is allocated to store the flag definitions of alias. Flag only modifies the default value of the flag and if user explicitly passes a value, explicit one is used.",
|
||||||
|
Type: []string{"array"},
|
||||||
|
Items: &spec.SchemaOrArray{
|
||||||
|
Schema: &spec.Schema{
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Default: map[string]interface{}{},
|
||||||
|
Ref: ref("k8s.io/kubectl/pkg/config/v1alpha1.CommandOverrideFlag"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: []string{"name", "command"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Dependencies: []string{
|
||||||
|
"k8s.io/kubectl/pkg/config/v1alpha1.CommandOverrideFlag"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func schema_kubectl_pkg_config_v1alpha1_CommandOverride(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||||
|
return common.OpenAPIDefinition{
|
||||||
|
Schema: spec.Schema{
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Description: "CommandOverride stores the commands and their associated flag's default values.",
|
||||||
|
Type: []string{"object"},
|
||||||
|
Properties: map[string]spec.Schema{
|
||||||
|
"command": {
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Description: "Command refers to a command whose flag's default value is changed.",
|
||||||
|
Default: "",
|
||||||
|
Type: []string{"string"},
|
||||||
|
Format: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"flags": {
|
||||||
|
VendorExtensible: spec.VendorExtensible{
|
||||||
|
Extensions: spec.Extensions{
|
||||||
|
"x-kubernetes-list-type": "atomic",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Description: "Flags is a list of flags storing different default values.",
|
||||||
|
Type: []string{"array"},
|
||||||
|
Items: &spec.SchemaOrArray{
|
||||||
|
Schema: &spec.Schema{
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Default: map[string]interface{}{},
|
||||||
|
Ref: ref("k8s.io/kubectl/pkg/config/v1alpha1.CommandOverrideFlag"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: []string{"command", "flags"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Dependencies: []string{
|
||||||
|
"k8s.io/kubectl/pkg/config/v1alpha1.CommandOverrideFlag"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func schema_kubectl_pkg_config_v1alpha1_CommandOverrideFlag(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||||
|
return common.OpenAPIDefinition{
|
||||||
|
Schema: spec.Schema{
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Description: "CommandOverrideFlag stores the name and the specified default value of the flag.",
|
||||||
|
Type: []string{"object"},
|
||||||
|
Properties: map[string]spec.Schema{
|
||||||
|
"name": {
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Description: "Flag name (long form, without dashes).",
|
||||||
|
Default: "",
|
||||||
|
Type: []string{"string"},
|
||||||
|
Format: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Description: "In a string format of a default value. It will be parsed by kubectl to the compatible value of the flag.",
|
||||||
|
Default: "",
|
||||||
|
Type: []string{"string"},
|
||||||
|
Format: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: []string{"name", "default"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func schema_kubectl_pkg_config_v1alpha1_Preference(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||||
|
return common.OpenAPIDefinition{
|
||||||
|
Schema: spec.Schema{
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Description: "Preference stores elements of KubeRC configuration file",
|
||||||
|
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: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"overrides": {
|
||||||
|
VendorExtensible: spec.VendorExtensible{
|
||||||
|
Extensions: spec.Extensions{
|
||||||
|
"x-kubernetes-list-type": "atomic",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Description: "overrides allows changing default flag values of commands. This is especially useful, when user doesn't want to explicitly set flags each time.",
|
||||||
|
Type: []string{"array"},
|
||||||
|
Items: &spec.SchemaOrArray{
|
||||||
|
Schema: &spec.Schema{
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Default: map[string]interface{}{},
|
||||||
|
Ref: ref("k8s.io/kubectl/pkg/config/v1alpha1.CommandOverride"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"aliases": {
|
||||||
|
VendorExtensible: spec.VendorExtensible{
|
||||||
|
Extensions: spec.Extensions{
|
||||||
|
"x-kubernetes-list-type": "atomic",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Description: "aliases allows defining command aliases for existing kubectl commands, with optional default flag values. If the alias name collides with a built-in command, built-in command always takes precedence. Flag overrides defined in the overrides section do NOT apply to aliases for the same command. kubectl [ALIAS NAME] [USER_FLAGS] [USER_EXPLICIT_ARGS] expands to kubectl [COMMAND] # built-in command alias points to\n [KUBERC_PREPEND_ARGS]\n [USER_FLAGS]\n [KUBERC_FLAGS] # rest of the flags that are not passed by user in [USER_FLAGS]\n [USER_EXPLICIT_ARGS]\n [KUBERC_APPEND_ARGS]\ne.g. - name: runx\n command: run\n flags:\n - name: image\n default: nginx\n appendArgs:\n - --\n - custom-arg1\nFor example, if user invokes \"kubectl runx test-pod\" command, this will be expanded to \"kubectl run --image=nginx test-pod -- custom-arg1\" - name: getn\n command: get\n flags:\n - name: output\n default: wide\n prependArgs:\n - node\n\"kubectl getn control-plane-1\" expands to \"kubectl get node control-plane-1 --output=wide\" \"kubectl getn control-plane-1 --output=json\" expands to \"kubectl get node --output=json control-plane-1\"",
|
||||||
|
Type: []string{"array"},
|
||||||
|
Items: &spec.SchemaOrArray{
|
||||||
|
Schema: &spec.Schema{
|
||||||
|
SchemaProps: spec.SchemaProps{
|
||||||
|
Default: map[string]interface{}{},
|
||||||
|
Ref: ref("k8s.io/kubectl/pkg/config/v1alpha1.AliasOverride"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Required: []string{"overrides", "aliases"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Dependencies: []string{
|
||||||
|
"k8s.io/kubectl/pkg/config/v1alpha1.AliasOverride", "k8s.io/kubectl/pkg/config/v1alpha1.CommandOverride"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func schema_k8sio_kubelet_config_v1_CredentialProvider(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
func schema_k8sio_kubelet_config_v1_CredentialProvider(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||||
return common.OpenAPIDefinition{
|
return common.OpenAPIDefinition{
|
||||||
Schema: spec.Schema{
|
Schema: spec.Schema{
|
||||||
|
@ -73,6 +73,7 @@ import (
|
|||||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||||
"k8s.io/kubectl/pkg/cmd/version"
|
"k8s.io/kubectl/pkg/cmd/version"
|
||||||
"k8s.io/kubectl/pkg/cmd/wait"
|
"k8s.io/kubectl/pkg/cmd/wait"
|
||||||
|
"k8s.io/kubectl/pkg/kuberc"
|
||||||
utilcomp "k8s.io/kubectl/pkg/util/completion"
|
utilcomp "k8s.io/kubectl/pkg/util/completion"
|
||||||
"k8s.io/kubectl/pkg/util/i18n"
|
"k8s.io/kubectl/pkg/util/i18n"
|
||||||
"k8s.io/kubectl/pkg/util/templates"
|
"k8s.io/kubectl/pkg/util/templates"
|
||||||
@ -361,6 +362,11 @@ func NewKubectlCommand(o KubectlOptions) *cobra.Command {
|
|||||||
|
|
||||||
flags.BoolVar(&warningsAsErrors, "warnings-as-errors", warningsAsErrors, "Treat warnings received from the server as errors and exit with a non-zero exit code")
|
flags.BoolVar(&warningsAsErrors, "warnings-as-errors", warningsAsErrors, "Treat warnings received from the server as errors and exit with a non-zero exit code")
|
||||||
|
|
||||||
|
pref := kuberc.NewPreferences()
|
||||||
|
if cmdutil.KubeRC.IsEnabled() {
|
||||||
|
pref.AddFlags(flags)
|
||||||
|
}
|
||||||
|
|
||||||
kubeConfigFlags := o.ConfigFlags
|
kubeConfigFlags := o.ConfigFlags
|
||||||
if kubeConfigFlags == nil {
|
if kubeConfigFlags == nil {
|
||||||
kubeConfigFlags = defaultConfigFlags().WithWarningPrinter(o.IOStreams)
|
kubeConfigFlags = defaultConfigFlags().WithWarningPrinter(o.IOStreams)
|
||||||
@ -490,6 +496,15 @@ func NewKubectlCommand(o KubectlOptions) *cobra.Command {
|
|||||||
// Stop warning about normalization of flags. That makes it possible to
|
// Stop warning about normalization of flags. That makes it possible to
|
||||||
// add the klog flags later.
|
// add the klog flags later.
|
||||||
cmds.SetGlobalNormalizationFunc(cliflag.WordSepNormalizeFunc)
|
cmds.SetGlobalNormalizationFunc(cliflag.WordSepNormalizeFunc)
|
||||||
|
|
||||||
|
if cmdutil.KubeRC.IsEnabled() {
|
||||||
|
_, err := pref.Apply(cmds, o.Arguments, o.IOStreams.ErrOut)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(o.IOStreams.ErrOut, "error occurred while applying preferences %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return cmds
|
return cmds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,6 +432,7 @@ const (
|
|||||||
PortForwardWebsockets FeatureGate = "KUBECTL_PORT_FORWARD_WEBSOCKETS"
|
PortForwardWebsockets FeatureGate = "KUBECTL_PORT_FORWARD_WEBSOCKETS"
|
||||||
// DebugCustomProfile should be dropped in 1.34
|
// DebugCustomProfile should be dropped in 1.34
|
||||||
DebugCustomProfile FeatureGate = "KUBECTL_DEBUG_CUSTOM_PROFILE"
|
DebugCustomProfile FeatureGate = "KUBECTL_DEBUG_CUSTOM_PROFILE"
|
||||||
|
KubeRC FeatureGate = "KUBECTL_KUBERC"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsEnabled returns true iff environment variable is set to true.
|
// IsEnabled returns true iff environment variable is set to true.
|
||||||
|
12
staging/src/k8s.io/kubectl/pkg/config/OWNERS
Normal file
12
staging/src/k8s.io/kubectl/pkg/config/OWNERS
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# See the OWNERS docs at https://go.k8s.io/owners
|
||||||
|
|
||||||
|
# Disable inheritance as this is an api owners file
|
||||||
|
options:
|
||||||
|
no_parent_owners: true
|
||||||
|
approvers:
|
||||||
|
- api-approvers
|
||||||
|
reviewers:
|
||||||
|
- api-reviewers
|
||||||
|
- sig-cli-reviewers
|
||||||
|
labels:
|
||||||
|
- kind/api-change
|
20
staging/src/k8s.io/kubectl/pkg/config/doc.go
Normal file
20
staging/src/k8s.io/kubectl/pkg/config/doc.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024 The Kubernetes 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
|
||||||
|
// +groupName=kubectl.config.k8s.io
|
||||||
|
|
||||||
|
package config // Package config import "k8s.io/kubectl/pkg/config"
|
32
staging/src/k8s.io/kubectl/pkg/config/install/install.go
Normal file
32
staging/src/k8s.io/kubectl/pkg/config/install/install.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024 The Kubernetes 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 install installs the experimental API group, making it available as
|
||||||
|
// an option to all of the API encoding/decoding machinery.
|
||||||
|
package install
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
|
"k8s.io/kubectl/pkg/config"
|
||||||
|
"k8s.io/kubectl/pkg/config/v1alpha1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Install registers the API group and adds types to a scheme
|
||||||
|
func Install(scheme *runtime.Scheme) {
|
||||||
|
utilruntime.Must(config.AddToScheme(scheme))
|
||||||
|
utilruntime.Must(v1alpha1.AddToScheme(scheme))
|
||||||
|
}
|
44
staging/src/k8s.io/kubectl/pkg/config/register.go
Normal file
44
staging/src/k8s.io/kubectl/pkg/config/register.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024 The Kubernetes 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 config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GroupName is the group name used in this package
|
||||||
|
const GroupName = "kubectl.config.k8s.io"
|
||||||
|
|
||||||
|
// SchemeGroupVersion is group version used to register these objects
|
||||||
|
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// SchemeBuilder is the scheme builder with scheme init functions to run for this API package
|
||||||
|
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||||
|
// AddToScheme is a global function that registers this API group & version to a scheme
|
||||||
|
AddToScheme = SchemeBuilder.AddToScheme
|
||||||
|
)
|
||||||
|
|
||||||
|
// addKnownTypes registers known types to the given scheme
|
||||||
|
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||||
|
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||||
|
&Preference{},
|
||||||
|
)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
103
staging/src/k8s.io/kubectl/pkg/config/types.go
Normal file
103
staging/src/k8s.io/kubectl/pkg/config/types.go
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024 The Kubernetes 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 config
|
||||||
|
|
||||||
|
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
||||||
|
// Preference stores elements of KubeRC configuration file
|
||||||
|
type Preference struct {
|
||||||
|
metav1.TypeMeta
|
||||||
|
|
||||||
|
// overrides allows changing default flag values of commands.
|
||||||
|
// This is especially useful, when user doesn't want to explicitly
|
||||||
|
// set flags each time.
|
||||||
|
// +optional
|
||||||
|
Overrides []CommandOverride
|
||||||
|
|
||||||
|
// aliases allows defining command aliases for existing kubectl commands, with optional default flag values.
|
||||||
|
// If the alias name collides with a built-in command, built-in command always takes precedence.
|
||||||
|
// Flag overrides defined in the overrides section do NOT apply to aliases for the same command.
|
||||||
|
// kubectl [ALIAS NAME] [USER_FLAGS] [USER_EXPLICIT_ARGS] expands to
|
||||||
|
// kubectl [COMMAND] # built-in command alias points to
|
||||||
|
// [KUBERC_PREPEND_ARGS]
|
||||||
|
// [USER_FLAGS]
|
||||||
|
// [KUBERC_FLAGS] # rest of the flags that are not passed by user in [USER_FLAGS]
|
||||||
|
// [USER_EXPLICIT_ARGS]
|
||||||
|
// [KUBERC_APPEND_ARGS]
|
||||||
|
// e.g.
|
||||||
|
// - name: runx
|
||||||
|
// command: run
|
||||||
|
// flags:
|
||||||
|
// - name: image
|
||||||
|
// default: nginx
|
||||||
|
// appendArgs:
|
||||||
|
// - --
|
||||||
|
// - custom-arg1
|
||||||
|
// For example, if user invokes "kubectl runx test-pod" command,
|
||||||
|
// this will be expanded to "kubectl run --image=nginx test-pod -- custom-arg1"
|
||||||
|
// - name: getn
|
||||||
|
// command: get
|
||||||
|
// flags:
|
||||||
|
// - name: output
|
||||||
|
// default: wide
|
||||||
|
// prependArgs:
|
||||||
|
// - node
|
||||||
|
// "kubectl getn control-plane-1" expands to "kubectl get node control-plane-1 --output=wide"
|
||||||
|
// "kubectl getn control-plane-1 --output=json" expands to "kubectl get node --output=json control-plane-1"
|
||||||
|
// +optional
|
||||||
|
Aliases []AliasOverride
|
||||||
|
}
|
||||||
|
|
||||||
|
// AliasOverride stores the alias definitions.
|
||||||
|
type AliasOverride struct {
|
||||||
|
// Name is the name of alias that can only include alphabetical characters
|
||||||
|
// If the alias name conflicts with the built-in command,
|
||||||
|
// built-in command will be used.
|
||||||
|
Name string
|
||||||
|
// Command is the single or set of commands to execute, such as "set env" or "create"
|
||||||
|
Command string
|
||||||
|
// PrependArgs stores the arguments such as resource names, etc.
|
||||||
|
// These arguments are inserted after the alias name.
|
||||||
|
PrependArgs []string
|
||||||
|
// AppendArgs stores the arguments such as resource names, etc.
|
||||||
|
// These arguments are appended to the USER_ARGS.
|
||||||
|
AppendArgs []string
|
||||||
|
// Flag is allocated to store the flag definitions of alias
|
||||||
|
Flags []CommandOverrideFlag
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommandOverride stores the commands and their associated flag's
|
||||||
|
// default values.
|
||||||
|
type CommandOverride struct {
|
||||||
|
// Command refers to a command whose flag's default value is changed.
|
||||||
|
Command string
|
||||||
|
// Flags is a list of flags storing different default values.
|
||||||
|
Flags []CommandOverrideFlag
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommandOverrideFlag stores the name and the specified default
|
||||||
|
// value of the flag.
|
||||||
|
type CommandOverrideFlag struct {
|
||||||
|
// Flag name (long form, without dashes).
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// In a string format of a default value. It will be parsed
|
||||||
|
// by kubectl to the compatible value of the flag.
|
||||||
|
Default string `json:"default"`
|
||||||
|
}
|
23
staging/src/k8s.io/kubectl/pkg/config/v1alpha1/doc.go
Normal file
23
staging/src/k8s.io/kubectl/pkg/config/v1alpha1/doc.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024 The Kubernetes 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
|
||||||
|
// +k8s:openapi-gen=true
|
||||||
|
// +groupName=kubectl.config.k8s.io
|
||||||
|
// +k8s:conversion-gen=k8s.io/kubectl/pkg/config
|
||||||
|
// +k8s:defaulter-gen=TypeMeta
|
||||||
|
|
||||||
|
package v1alpha1 // Package v1alpha1 import "k8s.io/kubectl/pkg/config/v1alpha1"
|
50
staging/src/k8s.io/kubectl/pkg/config/v1alpha1/register.go
Normal file
50
staging/src/k8s.io/kubectl/pkg/config/v1alpha1/register.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024 The Kubernetes 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 (
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GroupName is the group name used in this package
|
||||||
|
const GroupName = "kubectl.config.k8s.io"
|
||||||
|
|
||||||
|
// SchemeGroupVersion is group version used to register these objects
|
||||||
|
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"}
|
||||||
|
|
||||||
|
var (
|
||||||
|
SchemeBuilder runtime.SchemeBuilder
|
||||||
|
localSchemeBuilder = &SchemeBuilder
|
||||||
|
AddToScheme = localSchemeBuilder.AddToScheme
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// We only register manually written functions here. The registration of the
|
||||||
|
// generated functions takes place in the generated files. The separation
|
||||||
|
// makes the code compile even when the generated files are missing.
|
||||||
|
localSchemeBuilder.Register(addKnownTypes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// addKnownTypes registers known types to the given scheme
|
||||||
|
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||||
|
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||||
|
&Preference{},
|
||||||
|
)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
109
staging/src/k8s.io/kubectl/pkg/config/v1alpha1/types.go
Normal file
109
staging/src/k8s.io/kubectl/pkg/config/v1alpha1/types.go
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024 The Kubernetes 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:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
||||||
|
// Preference stores elements of KubeRC configuration file
|
||||||
|
type Preference struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
|
||||||
|
// overrides allows changing default flag values of commands.
|
||||||
|
// This is especially useful, when user doesn't want to explicitly
|
||||||
|
// set flags each time.
|
||||||
|
// +listType=atomic
|
||||||
|
Overrides []CommandOverride `json:"overrides"`
|
||||||
|
|
||||||
|
// aliases allows defining command aliases for existing kubectl commands, with optional default flag values.
|
||||||
|
// If the alias name collides with a built-in command, built-in command always takes precedence.
|
||||||
|
// Flag overrides defined in the overrides section do NOT apply to aliases for the same command.
|
||||||
|
// kubectl [ALIAS NAME] [USER_FLAGS] [USER_EXPLICIT_ARGS] expands to
|
||||||
|
// kubectl [COMMAND] # built-in command alias points to
|
||||||
|
// [KUBERC_PREPEND_ARGS]
|
||||||
|
// [USER_FLAGS]
|
||||||
|
// [KUBERC_FLAGS] # rest of the flags that are not passed by user in [USER_FLAGS]
|
||||||
|
// [USER_EXPLICIT_ARGS]
|
||||||
|
// [KUBERC_APPEND_ARGS]
|
||||||
|
// e.g.
|
||||||
|
// - name: runx
|
||||||
|
// command: run
|
||||||
|
// flags:
|
||||||
|
// - name: image
|
||||||
|
// default: nginx
|
||||||
|
// appendArgs:
|
||||||
|
// - --
|
||||||
|
// - custom-arg1
|
||||||
|
// For example, if user invokes "kubectl runx test-pod" command,
|
||||||
|
// this will be expanded to "kubectl run --image=nginx test-pod -- custom-arg1"
|
||||||
|
// - name: getn
|
||||||
|
// command: get
|
||||||
|
// flags:
|
||||||
|
// - name: output
|
||||||
|
// default: wide
|
||||||
|
// prependArgs:
|
||||||
|
// - node
|
||||||
|
// "kubectl getn control-plane-1" expands to "kubectl get node control-plane-1 --output=wide"
|
||||||
|
// "kubectl getn control-plane-1 --output=json" expands to "kubectl get node --output=json control-plane-1"
|
||||||
|
// +listType=atomic
|
||||||
|
Aliases []AliasOverride `json:"aliases"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AliasOverride stores the alias definitions.
|
||||||
|
type AliasOverride struct {
|
||||||
|
// Name is the name of alias that can only include alphabetical characters
|
||||||
|
// If the alias name conflicts with the built-in command,
|
||||||
|
// built-in command will be used.
|
||||||
|
Name string `json:"name"`
|
||||||
|
// Command is the single or set of commands to execute, such as "set env" or "create"
|
||||||
|
Command string `json:"command"`
|
||||||
|
// PrependArgs stores the arguments such as resource names, etc.
|
||||||
|
// These arguments are inserted after the alias name.
|
||||||
|
// +listType=atomic
|
||||||
|
PrependArgs []string `json:"prependArgs,omitempty"`
|
||||||
|
// AppendArgs stores the arguments such as resource names, etc.
|
||||||
|
// These arguments are appended to the USER_ARGS.
|
||||||
|
// +listType=atomic
|
||||||
|
AppendArgs []string `json:"appendArgs,omitempty"`
|
||||||
|
// Flag is allocated to store the flag definitions of alias.
|
||||||
|
// Flag only modifies the default value of the flag and if
|
||||||
|
// user explicitly passes a value, explicit one is used.
|
||||||
|
// +listType=atomic
|
||||||
|
Flags []CommandOverrideFlag `json:"flags,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommandOverride stores the commands and their associated flag's
|
||||||
|
// default values.
|
||||||
|
type CommandOverride struct {
|
||||||
|
// Command refers to a command whose flag's default value is changed.
|
||||||
|
Command string `json:"command"`
|
||||||
|
// Flags is a list of flags storing different default values.
|
||||||
|
// +listType=atomic
|
||||||
|
Flags []CommandOverrideFlag `json:"flags"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommandOverrideFlag stores the name and the specified default
|
||||||
|
// value of the flag.
|
||||||
|
type CommandOverrideFlag struct {
|
||||||
|
// Flag name (long form, without dashes).
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// In a string format of a default value. It will be parsed
|
||||||
|
// by kubectl to the compatible value of the flag.
|
||||||
|
Default string `json:"default"`
|
||||||
|
}
|
174
staging/src/k8s.io/kubectl/pkg/config/v1alpha1/zz_generated.conversion.go
generated
Normal file
174
staging/src/k8s.io/kubectl/pkg/config/v1alpha1/zz_generated.conversion.go
generated
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
//go:build !ignore_autogenerated
|
||||||
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The Kubernetes 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 conversion-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
unsafe "unsafe"
|
||||||
|
|
||||||
|
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||||
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
|
config "k8s.io/kubectl/pkg/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
localSchemeBuilder.Register(RegisterConversions)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterConversions adds conversion functions to the given scheme.
|
||||||
|
// Public to allow building arbitrary schemes.
|
||||||
|
func RegisterConversions(s *runtime.Scheme) error {
|
||||||
|
if err := s.AddGeneratedConversionFunc((*AliasOverride)(nil), (*config.AliasOverride)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convert_v1alpha1_AliasOverride_To_config_AliasOverride(a.(*AliasOverride), b.(*config.AliasOverride), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*config.AliasOverride)(nil), (*AliasOverride)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convert_config_AliasOverride_To_v1alpha1_AliasOverride(a.(*config.AliasOverride), b.(*AliasOverride), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*CommandOverride)(nil), (*config.CommandOverride)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convert_v1alpha1_CommandOverride_To_config_CommandOverride(a.(*CommandOverride), b.(*config.CommandOverride), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*config.CommandOverride)(nil), (*CommandOverride)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convert_config_CommandOverride_To_v1alpha1_CommandOverride(a.(*config.CommandOverride), b.(*CommandOverride), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*CommandOverrideFlag)(nil), (*config.CommandOverrideFlag)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convert_v1alpha1_CommandOverrideFlag_To_config_CommandOverrideFlag(a.(*CommandOverrideFlag), b.(*config.CommandOverrideFlag), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*config.CommandOverrideFlag)(nil), (*CommandOverrideFlag)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convert_config_CommandOverrideFlag_To_v1alpha1_CommandOverrideFlag(a.(*config.CommandOverrideFlag), b.(*CommandOverrideFlag), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*Preference)(nil), (*config.Preference)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convert_v1alpha1_Preference_To_config_Preference(a.(*Preference), b.(*config.Preference), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*config.Preference)(nil), (*Preference)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convert_config_Preference_To_v1alpha1_Preference(a.(*config.Preference), b.(*Preference), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvert_v1alpha1_AliasOverride_To_config_AliasOverride(in *AliasOverride, out *config.AliasOverride, s conversion.Scope) error {
|
||||||
|
out.Name = in.Name
|
||||||
|
out.Command = in.Command
|
||||||
|
out.PrependArgs = *(*[]string)(unsafe.Pointer(&in.PrependArgs))
|
||||||
|
out.AppendArgs = *(*[]string)(unsafe.Pointer(&in.AppendArgs))
|
||||||
|
out.Flags = *(*[]config.CommandOverrideFlag)(unsafe.Pointer(&in.Flags))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_v1alpha1_AliasOverride_To_config_AliasOverride is an autogenerated conversion function.
|
||||||
|
func Convert_v1alpha1_AliasOverride_To_config_AliasOverride(in *AliasOverride, out *config.AliasOverride, s conversion.Scope) error {
|
||||||
|
return autoConvert_v1alpha1_AliasOverride_To_config_AliasOverride(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvert_config_AliasOverride_To_v1alpha1_AliasOverride(in *config.AliasOverride, out *AliasOverride, s conversion.Scope) error {
|
||||||
|
out.Name = in.Name
|
||||||
|
out.Command = in.Command
|
||||||
|
out.PrependArgs = *(*[]string)(unsafe.Pointer(&in.PrependArgs))
|
||||||
|
out.AppendArgs = *(*[]string)(unsafe.Pointer(&in.AppendArgs))
|
||||||
|
out.Flags = *(*[]CommandOverrideFlag)(unsafe.Pointer(&in.Flags))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_config_AliasOverride_To_v1alpha1_AliasOverride is an autogenerated conversion function.
|
||||||
|
func Convert_config_AliasOverride_To_v1alpha1_AliasOverride(in *config.AliasOverride, out *AliasOverride, s conversion.Scope) error {
|
||||||
|
return autoConvert_config_AliasOverride_To_v1alpha1_AliasOverride(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvert_v1alpha1_CommandOverride_To_config_CommandOverride(in *CommandOverride, out *config.CommandOverride, s conversion.Scope) error {
|
||||||
|
out.Command = in.Command
|
||||||
|
out.Flags = *(*[]config.CommandOverrideFlag)(unsafe.Pointer(&in.Flags))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_v1alpha1_CommandOverride_To_config_CommandOverride is an autogenerated conversion function.
|
||||||
|
func Convert_v1alpha1_CommandOverride_To_config_CommandOverride(in *CommandOverride, out *config.CommandOverride, s conversion.Scope) error {
|
||||||
|
return autoConvert_v1alpha1_CommandOverride_To_config_CommandOverride(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvert_config_CommandOverride_To_v1alpha1_CommandOverride(in *config.CommandOverride, out *CommandOverride, s conversion.Scope) error {
|
||||||
|
out.Command = in.Command
|
||||||
|
out.Flags = *(*[]CommandOverrideFlag)(unsafe.Pointer(&in.Flags))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_config_CommandOverride_To_v1alpha1_CommandOverride is an autogenerated conversion function.
|
||||||
|
func Convert_config_CommandOverride_To_v1alpha1_CommandOverride(in *config.CommandOverride, out *CommandOverride, s conversion.Scope) error {
|
||||||
|
return autoConvert_config_CommandOverride_To_v1alpha1_CommandOverride(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvert_v1alpha1_CommandOverrideFlag_To_config_CommandOverrideFlag(in *CommandOverrideFlag, out *config.CommandOverrideFlag, s conversion.Scope) error {
|
||||||
|
out.Name = in.Name
|
||||||
|
out.Default = in.Default
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_v1alpha1_CommandOverrideFlag_To_config_CommandOverrideFlag is an autogenerated conversion function.
|
||||||
|
func Convert_v1alpha1_CommandOverrideFlag_To_config_CommandOverrideFlag(in *CommandOverrideFlag, out *config.CommandOverrideFlag, s conversion.Scope) error {
|
||||||
|
return autoConvert_v1alpha1_CommandOverrideFlag_To_config_CommandOverrideFlag(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvert_config_CommandOverrideFlag_To_v1alpha1_CommandOverrideFlag(in *config.CommandOverrideFlag, out *CommandOverrideFlag, s conversion.Scope) error {
|
||||||
|
out.Name = in.Name
|
||||||
|
out.Default = in.Default
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_config_CommandOverrideFlag_To_v1alpha1_CommandOverrideFlag is an autogenerated conversion function.
|
||||||
|
func Convert_config_CommandOverrideFlag_To_v1alpha1_CommandOverrideFlag(in *config.CommandOverrideFlag, out *CommandOverrideFlag, s conversion.Scope) error {
|
||||||
|
return autoConvert_config_CommandOverrideFlag_To_v1alpha1_CommandOverrideFlag(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvert_v1alpha1_Preference_To_config_Preference(in *Preference, out *config.Preference, s conversion.Scope) error {
|
||||||
|
out.Overrides = *(*[]config.CommandOverride)(unsafe.Pointer(&in.Overrides))
|
||||||
|
out.Aliases = *(*[]config.AliasOverride)(unsafe.Pointer(&in.Aliases))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_v1alpha1_Preference_To_config_Preference is an autogenerated conversion function.
|
||||||
|
func Convert_v1alpha1_Preference_To_config_Preference(in *Preference, out *config.Preference, s conversion.Scope) error {
|
||||||
|
return autoConvert_v1alpha1_Preference_To_config_Preference(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvert_config_Preference_To_v1alpha1_Preference(in *config.Preference, out *Preference, s conversion.Scope) error {
|
||||||
|
out.Overrides = *(*[]CommandOverride)(unsafe.Pointer(&in.Overrides))
|
||||||
|
out.Aliases = *(*[]AliasOverride)(unsafe.Pointer(&in.Aliases))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_config_Preference_To_v1alpha1_Preference is an autogenerated conversion function.
|
||||||
|
func Convert_config_Preference_To_v1alpha1_Preference(in *config.Preference, out *Preference, s conversion.Scope) error {
|
||||||
|
return autoConvert_config_Preference_To_v1alpha1_Preference(in, out, s)
|
||||||
|
}
|
133
staging/src/k8s.io/kubectl/pkg/config/v1alpha1/zz_generated.deepcopy.go
generated
Normal file
133
staging/src/k8s.io/kubectl/pkg/config/v1alpha1/zz_generated.deepcopy.go
generated
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
//go:build !ignore_autogenerated
|
||||||
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The Kubernetes 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 (
|
||||||
|
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 *AliasOverride) DeepCopyInto(out *AliasOverride) {
|
||||||
|
*out = *in
|
||||||
|
if in.PrependArgs != nil {
|
||||||
|
in, out := &in.PrependArgs, &out.PrependArgs
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
if in.AppendArgs != nil {
|
||||||
|
in, out := &in.AppendArgs, &out.AppendArgs
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
if in.Flags != nil {
|
||||||
|
in, out := &in.Flags, &out.Flags
|
||||||
|
*out = make([]CommandOverrideFlag, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AliasOverride.
|
||||||
|
func (in *AliasOverride) DeepCopy() *AliasOverride {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(AliasOverride)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *CommandOverride) DeepCopyInto(out *CommandOverride) {
|
||||||
|
*out = *in
|
||||||
|
if in.Flags != nil {
|
||||||
|
in, out := &in.Flags, &out.Flags
|
||||||
|
*out = make([]CommandOverrideFlag, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommandOverride.
|
||||||
|
func (in *CommandOverride) DeepCopy() *CommandOverride {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(CommandOverride)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *CommandOverrideFlag) DeepCopyInto(out *CommandOverrideFlag) {
|
||||||
|
*out = *in
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommandOverrideFlag.
|
||||||
|
func (in *CommandOverrideFlag) DeepCopy() *CommandOverrideFlag {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(CommandOverrideFlag)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *Preference) DeepCopyInto(out *Preference) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
if in.Overrides != nil {
|
||||||
|
in, out := &in.Overrides, &out.Overrides
|
||||||
|
*out = make([]CommandOverride, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if in.Aliases != nil {
|
||||||
|
in, out := &in.Aliases, &out.Aliases
|
||||||
|
*out = make([]AliasOverride, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Preference.
|
||||||
|
func (in *Preference) DeepCopy() *Preference {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(Preference)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *Preference) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
33
staging/src/k8s.io/kubectl/pkg/config/v1alpha1/zz_generated.defaults.go
generated
Normal file
33
staging/src/k8s.io/kubectl/pkg/config/v1alpha1/zz_generated.defaults.go
generated
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
//go:build !ignore_autogenerated
|
||||||
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The Kubernetes 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 defaulter-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RegisterDefaults adds defaulters functions to the given scheme.
|
||||||
|
// Public to allow building arbitrary schemes.
|
||||||
|
// All generated defaulters are covering - they call all nested defaulters.
|
||||||
|
func RegisterDefaults(scheme *runtime.Scheme) error {
|
||||||
|
return nil
|
||||||
|
}
|
133
staging/src/k8s.io/kubectl/pkg/config/zz_generated.deepcopy.go
generated
Normal file
133
staging/src/k8s.io/kubectl/pkg/config/zz_generated.deepcopy.go
generated
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
//go:build !ignore_autogenerated
|
||||||
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The Kubernetes 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 config
|
||||||
|
|
||||||
|
import (
|
||||||
|
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 *AliasOverride) DeepCopyInto(out *AliasOverride) {
|
||||||
|
*out = *in
|
||||||
|
if in.PrependArgs != nil {
|
||||||
|
in, out := &in.PrependArgs, &out.PrependArgs
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
if in.AppendArgs != nil {
|
||||||
|
in, out := &in.AppendArgs, &out.AppendArgs
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
if in.Flags != nil {
|
||||||
|
in, out := &in.Flags, &out.Flags
|
||||||
|
*out = make([]CommandOverrideFlag, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AliasOverride.
|
||||||
|
func (in *AliasOverride) DeepCopy() *AliasOverride {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(AliasOverride)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *CommandOverride) DeepCopyInto(out *CommandOverride) {
|
||||||
|
*out = *in
|
||||||
|
if in.Flags != nil {
|
||||||
|
in, out := &in.Flags, &out.Flags
|
||||||
|
*out = make([]CommandOverrideFlag, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommandOverride.
|
||||||
|
func (in *CommandOverride) DeepCopy() *CommandOverride {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(CommandOverride)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *CommandOverrideFlag) DeepCopyInto(out *CommandOverrideFlag) {
|
||||||
|
*out = *in
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommandOverrideFlag.
|
||||||
|
func (in *CommandOverrideFlag) DeepCopy() *CommandOverrideFlag {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(CommandOverrideFlag)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *Preference) DeepCopyInto(out *Preference) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
if in.Overrides != nil {
|
||||||
|
in, out := &in.Overrides, &out.Overrides
|
||||||
|
*out = make([]CommandOverride, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if in.Aliases != nil {
|
||||||
|
in, out := &in.Aliases, &out.Aliases
|
||||||
|
*out = make([]AliasOverride, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Preference.
|
||||||
|
func (in *Preference) DeepCopy() *Preference {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(Preference)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *Preference) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
458
staging/src/k8s.io/kubectl/pkg/kuberc/kuberc.go
Normal file
458
staging/src/k8s.io/kubectl/pkg/kuberc/kuberc.go
Normal file
@ -0,0 +1,458 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2025 The Kubernetes 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 kuberc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"k8s.io/kubectl/pkg/config"
|
||||||
|
kuberc "k8s.io/kubectl/pkg/config/install"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
|
"k8s.io/client-go/util/homedir"
|
||||||
|
)
|
||||||
|
|
||||||
|
const RecommendedKubeRCFileName = "kuberc"
|
||||||
|
|
||||||
|
var (
|
||||||
|
RecommendedConfigDir = filepath.Join(homedir.HomeDir(), clientcmd.RecommendedHomeDir)
|
||||||
|
RecommendedKubeRCFile = filepath.Join(RecommendedConfigDir, RecommendedKubeRCFileName)
|
||||||
|
|
||||||
|
aliasNameRegex = regexp.MustCompile("^[a-zA-Z]+$")
|
||||||
|
shortHandRegex = regexp.MustCompile("^-[a-zA-Z]+$")
|
||||||
|
|
||||||
|
scheme = runtime.NewScheme()
|
||||||
|
strictCodecs = serializer.NewCodecFactory(scheme, serializer.EnableStrict)
|
||||||
|
lenientCodecs = serializer.NewCodecFactory(scheme, serializer.DisableStrict)
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
kuberc.Install(scheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PreferencesHandler is responsible for setting default flags
|
||||||
|
// arguments based on user's kuberc configuration.
|
||||||
|
type PreferencesHandler interface {
|
||||||
|
AddFlags(flags *pflag.FlagSet)
|
||||||
|
Apply(rootCmd *cobra.Command, args []string, errOut io.Writer) ([]string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preferences stores the kuberc file coming either from environment variable
|
||||||
|
// or file from set in flag or the default kuberc path.
|
||||||
|
type Preferences struct {
|
||||||
|
getPreferencesFunc func(kuberc string, errOut io.Writer) (*config.Preference, error)
|
||||||
|
|
||||||
|
aliases map[string]struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPreferences returns initialized Prefrences object.
|
||||||
|
func NewPreferences() PreferencesHandler {
|
||||||
|
return &Preferences{
|
||||||
|
getPreferencesFunc: DefaultGetPreferences,
|
||||||
|
aliases: make(map[string]struct{}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type aliasing struct {
|
||||||
|
appendArgs []string
|
||||||
|
prependArgs []string
|
||||||
|
flags []config.CommandOverrideFlag
|
||||||
|
command *cobra.Command
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddFlags adds kuberc related flags into the command.
|
||||||
|
func (p *Preferences) AddFlags(flags *pflag.FlagSet) {
|
||||||
|
flags.String("kuberc", "", "Path to the kuberc file to use for preferences. This can be disabled by exporting KUBECTL_KUBERC=false.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply firstly applies the aliases in the preferences file and secondly overrides
|
||||||
|
// the default values of flags.
|
||||||
|
func (p *Preferences) Apply(rootCmd *cobra.Command, args []string, errOut io.Writer) ([]string, error) {
|
||||||
|
if len(args) <= 1 {
|
||||||
|
return args, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
kubercPath, err := getExplicitKuberc(args)
|
||||||
|
if err != nil {
|
||||||
|
return args, err
|
||||||
|
}
|
||||||
|
kuberc, err := p.getPreferencesFunc(kubercPath, errOut)
|
||||||
|
if err != nil {
|
||||||
|
return args, fmt.Errorf("kuberc error %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if kuberc == nil {
|
||||||
|
return args, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate(kuberc)
|
||||||
|
if err != nil {
|
||||||
|
return args, err
|
||||||
|
}
|
||||||
|
|
||||||
|
args, err = p.applyAliases(rootCmd, kuberc, args, errOut)
|
||||||
|
if err != nil {
|
||||||
|
return args, err
|
||||||
|
}
|
||||||
|
err = p.applyOverrides(rootCmd, kuberc, args, errOut)
|
||||||
|
if err != nil {
|
||||||
|
return args, err
|
||||||
|
}
|
||||||
|
return args, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// applyOverrides finds the command and sets the defaulted flag values in kuberc.
|
||||||
|
func (p *Preferences) applyOverrides(rootCmd *cobra.Command, kuberc *config.Preference, args []string, errOut io.Writer) error {
|
||||||
|
args = args[1:]
|
||||||
|
cmd, _, err := rootCmd.Find(args)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range kuberc.Overrides {
|
||||||
|
parsedCmds := strings.Fields(c.Command)
|
||||||
|
overrideCmd, _, err := rootCmd.Find(parsedCmds)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(errOut, "Warning: command %q not found to set kuberc override\n", c.Command)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if overrideCmd.Name() != cmd.Name() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := p.aliases[cmd.Name()]; ok {
|
||||||
|
return fmt.Errorf("alias %s can not be overridden", cmd.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function triggers merging the persistent flags in the parent commands.
|
||||||
|
_ = cmd.InheritedFlags()
|
||||||
|
|
||||||
|
allShorthands := make(map[string]struct{})
|
||||||
|
cmd.Flags().VisitAll(func(flag *pflag.Flag) {
|
||||||
|
if flag.Shorthand != "" {
|
||||||
|
allShorthands[flag.Shorthand] = struct{}{}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, fl := range c.Flags {
|
||||||
|
existingFlag := cmd.Flag(fl.Name)
|
||||||
|
if existingFlag == nil {
|
||||||
|
return fmt.Errorf("invalid flag %s for command %s", fl.Name, c.Command)
|
||||||
|
}
|
||||||
|
if searchInArgs(existingFlag.Name, existingFlag.Shorthand, allShorthands, args) {
|
||||||
|
// Don't modify the value implicitly, if it is passed in args explicitly
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
err = cmd.Flags().Set(fl.Name, fl.Default)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not apply override value %s to flag %s in command %s err: %w", fl.Default, fl.Name, c.Command, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// applyAliases firstly appends all defined aliases in kuberc file to the root command.
|
||||||
|
// Since there may be several alias definitions belonging to the same command, it extracts the
|
||||||
|
// alias that is currently executed from args. After that it sets the flag definitions in alias as default values
|
||||||
|
// of the command. Lastly, others parameters (e.g. resources, etc.) that are passed as arguments in kuberc
|
||||||
|
// is appended into the command args.
|
||||||
|
func (p *Preferences) applyAliases(rootCmd *cobra.Command, kuberc *config.Preference, args []string, errOut io.Writer) ([]string, error) {
|
||||||
|
_, _, err := rootCmd.Find(args[1:])
|
||||||
|
if err == nil {
|
||||||
|
// Command is found, no need to continue for aliasing
|
||||||
|
return args, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var aliasArgs *aliasing
|
||||||
|
|
||||||
|
var commandName string // first "non-flag" arguments
|
||||||
|
var commandIndex int
|
||||||
|
for index, arg := range args[1:] {
|
||||||
|
if !strings.HasPrefix(arg, "-") {
|
||||||
|
commandName = arg
|
||||||
|
commandIndex = index + 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, alias := range kuberc.Aliases {
|
||||||
|
p.aliases[alias.Name] = struct{}{}
|
||||||
|
if alias.Name != commandName {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// do not allow shadowing built-ins
|
||||||
|
if _, _, err := rootCmd.Find([]string{alias.Name}); err == nil {
|
||||||
|
fmt.Fprintf(errOut, "Warning: Setting alias %q to a built-in command is not supported\n", alias.Name)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
commands := strings.Fields(alias.Command)
|
||||||
|
existingCmd, flags, err := rootCmd.Find(commands)
|
||||||
|
if err != nil {
|
||||||
|
return args, fmt.Errorf("command %q not found to set alias %q: %v", alias.Command, alias.Name, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
newCmd := *existingCmd
|
||||||
|
newCmd.Use = alias.Name
|
||||||
|
newCmd.Aliases = []string{}
|
||||||
|
aliasCmd := &newCmd
|
||||||
|
|
||||||
|
aliasArgs = &aliasing{
|
||||||
|
prependArgs: alias.PrependArgs,
|
||||||
|
appendArgs: alias.AppendArgs,
|
||||||
|
flags: alias.Flags,
|
||||||
|
command: aliasCmd,
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if aliasArgs == nil {
|
||||||
|
// pursue with the current behavior.
|
||||||
|
// This might be a built-in command, external plugin, etc.
|
||||||
|
return args, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
rootCmd.AddCommand(aliasArgs.command)
|
||||||
|
|
||||||
|
foundAliasCmd, _, err := rootCmd.Find([]string{commandName})
|
||||||
|
if err != nil {
|
||||||
|
return args, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function triggers merging the persistent flags in the parent commands.
|
||||||
|
_ = foundAliasCmd.InheritedFlags()
|
||||||
|
|
||||||
|
allShorthands := make(map[string]struct{})
|
||||||
|
foundAliasCmd.Flags().VisitAll(func(flag *pflag.Flag) {
|
||||||
|
if flag.Shorthand != "" {
|
||||||
|
allShorthands[flag.Shorthand] = struct{}{}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, fl := range aliasArgs.flags {
|
||||||
|
existingFlag := foundAliasCmd.Flag(fl.Name)
|
||||||
|
if existingFlag == nil {
|
||||||
|
return args, fmt.Errorf("invalid alias flag %s in alias %s", fl.Name, args[0])
|
||||||
|
}
|
||||||
|
if searchInArgs(existingFlag.Name, existingFlag.Shorthand, allShorthands, args) {
|
||||||
|
// Don't modify the value implicitly, if it is passed in args explicitly
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
err = foundAliasCmd.Flags().Set(fl.Name, fl.Default)
|
||||||
|
if err != nil {
|
||||||
|
return args, fmt.Errorf("could not apply value %s to flag %s in alias %s err: %w", fl.Default, fl.Name, args[0], err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(aliasArgs.prependArgs) > 0 {
|
||||||
|
// prependArgs defined in kuberc should be inserted after the alias name.
|
||||||
|
if commandIndex+1 >= len(args) {
|
||||||
|
// command is the last item, we simply append just like appendArgs
|
||||||
|
args = append(args, aliasArgs.prependArgs...)
|
||||||
|
} else {
|
||||||
|
args = append(args[:commandIndex+1], append(aliasArgs.prependArgs, args[commandIndex+1:]...)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(aliasArgs.appendArgs) > 0 {
|
||||||
|
// appendArgs defined in kuberc should be appended to actual args.
|
||||||
|
args = append(args, aliasArgs.appendArgs...)
|
||||||
|
}
|
||||||
|
// Cobra (command.go#L1078) appends only root command's args into the actual args and ignores the others.
|
||||||
|
// We are appending the additional args defined in kuberc in here and
|
||||||
|
// expect that it will be passed along to the actual command.
|
||||||
|
rootCmd.SetArgs(args[1:])
|
||||||
|
return args, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultGetPreferences returns KubeRCConfiguration.
|
||||||
|
// If users sets kuberc file explicitly in --kuberc flag, it has the highest
|
||||||
|
// priority. If not specified, it looks for in KUBERC environment variable.
|
||||||
|
// If KUBERC is also not set, it falls back to default .kuberc file at the same location
|
||||||
|
// where kubeconfig's defaults are residing in.
|
||||||
|
// If KUBERC is set to "off", kuberc will be turned off and original behaviors in kubectl will be applied.
|
||||||
|
func DefaultGetPreferences(kuberc string, errOut io.Writer) (*config.Preference, error) {
|
||||||
|
if val := os.Getenv("KUBERC"); val == "off" {
|
||||||
|
if kuberc != "" {
|
||||||
|
return nil, fmt.Errorf("disabling kuberc via KUBERC=off and passing kuberc flag are mutually exclusive")
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
kubeRCFile := RecommendedKubeRCFile
|
||||||
|
explicitly := false
|
||||||
|
if kuberc != "" {
|
||||||
|
kubeRCFile = kuberc
|
||||||
|
explicitly = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if kubeRCFile == "" && os.Getenv("KUBERC") != "" {
|
||||||
|
kubeRCFile = os.Getenv("KUBERC")
|
||||||
|
explicitly = true
|
||||||
|
}
|
||||||
|
|
||||||
|
preference, err := decodePreference(kubeRCFile)
|
||||||
|
switch {
|
||||||
|
case explicitly && preference != nil && runtime.IsStrictDecodingError(err):
|
||||||
|
// if explicitly requested, just warn about strict decoding errors if we got a usable Preference object back
|
||||||
|
fmt.Fprintf(errOut, "kuberc: ignoring strict decoding error in %s: %v", kubeRCFile, err)
|
||||||
|
return preference, nil
|
||||||
|
|
||||||
|
case explicitly && err != nil:
|
||||||
|
// if explicitly requested, error on any error other than a StrictDecodingError
|
||||||
|
return nil, fmt.Errorf("kuberc: %w", err)
|
||||||
|
|
||||||
|
case !explicitly && os.IsNotExist(err):
|
||||||
|
// if not explicitly requested, silently ignore missing kuberc
|
||||||
|
return nil, nil
|
||||||
|
|
||||||
|
case !explicitly && err != nil:
|
||||||
|
// if not explicitly requested, only warn on any other error
|
||||||
|
fmt.Fprintf(errOut, "kuberc: no preferences loaded from %s: %v", kubeRCFile, err)
|
||||||
|
return nil, nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return preference, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normally, we should extract this value directly from kuberc flag.
|
||||||
|
// However, flag values are set during the command execution and
|
||||||
|
// we are in very early stages to prepare commands prior to execute them.
|
||||||
|
// Besides, we only need kuberc flag value in this stage.
|
||||||
|
func getExplicitKuberc(args []string) (string, error) {
|
||||||
|
var kubercPath string
|
||||||
|
for i, arg := range args {
|
||||||
|
if arg == "--" {
|
||||||
|
// flags after "--" does not represent any flag of
|
||||||
|
// the command. We should short cut the iteration in here.
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if arg == "--kuberc" {
|
||||||
|
if i+1 < len(args) {
|
||||||
|
kubercPath = args[i+1]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("kuberc file is not found")
|
||||||
|
} else if strings.Contains(arg, "--kuberc=") {
|
||||||
|
parg := strings.Split(arg, "=")
|
||||||
|
if len(parg) > 1 && parg[1] != "" {
|
||||||
|
kubercPath = parg[1]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("kuberc file is not found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if kubercPath == "" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return kubercPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// searchInArgs searches the given key in the args and returns
|
||||||
|
// true, if it finds. Otherwise, it returns false.
|
||||||
|
func searchInArgs(flagName string, shorthand string, allShorthands map[string]struct{}, args []string) bool {
|
||||||
|
for _, arg := range args {
|
||||||
|
// if flag is set in args in "--flag value" or "--flag=value" format,
|
||||||
|
// we should return it as found
|
||||||
|
if fmt.Sprintf("--%s", flagName) == arg || strings.HasPrefix(arg, fmt.Sprintf("--%s=", flagName)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if shorthand == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// shorthand can be in "-n value" or "-nvalue" format
|
||||||
|
// it is guaranteed that shorthand is one letter. So that
|
||||||
|
// checking just the prefix -oyaml also finds --output.
|
||||||
|
if strings.HasPrefix(arg, fmt.Sprintf("-%s", shorthand)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !shortHandRegex.MatchString(arg) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove prefix "-"
|
||||||
|
arg = arg[1:]
|
||||||
|
// short hands can be in a combined "-abc" format.
|
||||||
|
// First we need to ensure that all the values are shorthand to safely search ours.
|
||||||
|
// Because we know that "-abcvalue" is not valid. So that we need to be sure that if we find
|
||||||
|
// "b" it correctly refers to the shorthand "b" not arbitrary value "-cargb".
|
||||||
|
arbitraryFound := false
|
||||||
|
for _, runeValue := range shorthand {
|
||||||
|
if _, ok := allShorthands[string(runeValue)]; !ok {
|
||||||
|
arbitraryFound = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if arbitraryFound {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// verified that all values are short hand. Now search ours
|
||||||
|
if strings.Contains(arg, shorthand) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func validate(plugin *config.Preference) error {
|
||||||
|
validateFlag := func(flags []config.CommandOverrideFlag) error {
|
||||||
|
for _, flag := range flags {
|
||||||
|
if strings.HasPrefix(flag.Name, "-") {
|
||||||
|
return fmt.Errorf("flag name %s should be in long form without dashes", flag.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
aliases := make(map[string]struct{})
|
||||||
|
for _, alias := range plugin.Aliases {
|
||||||
|
if !aliasNameRegex.MatchString(alias.Name) {
|
||||||
|
return fmt.Errorf("invalid alias name, can only include alphabetical characters")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := validateFlag(alias.Flags); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := aliases[alias.Name]; ok {
|
||||||
|
return fmt.Errorf("duplicate alias name %s", alias.Name)
|
||||||
|
}
|
||||||
|
aliases[alias.Name] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, override := range plugin.Overrides {
|
||||||
|
if err := validateFlag(override.Flags); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
2723
staging/src/k8s.io/kubectl/pkg/kuberc/kuberc_test.go
Normal file
2723
staging/src/k8s.io/kubectl/pkg/kuberc/kuberc_test.go
Normal file
File diff suppressed because it is too large
Load Diff
101
staging/src/k8s.io/kubectl/pkg/kuberc/marshal.go
Normal file
101
staging/src/k8s.io/kubectl/pkg/kuberc/marshal.go
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024 The Kubernetes 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 kuberc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
utilyaml "k8s.io/apimachinery/pkg/util/yaml"
|
||||||
|
|
||||||
|
"k8s.io/kubectl/pkg/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
// decodePreference iterates over the yamls in kuberc file to find the supported kuberc version.
|
||||||
|
// Once it finds, it returns the compatible kuberc object as well as accumulated errors during the iteration.
|
||||||
|
func decodePreference(kubercFile string) (*config.Preference, error) {
|
||||||
|
kubercBytes, err := os.ReadFile(kubercFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
attemptedItems := 0
|
||||||
|
reader := utilyaml.NewYAMLReader(bufio.NewReader(bytes.NewBuffer(kubercBytes)))
|
||||||
|
for {
|
||||||
|
doc, readErr := reader.Read()
|
||||||
|
if errors.Is(readErr, io.EOF) {
|
||||||
|
// no more entries, expected when we reach the end of the file
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if readErr != nil {
|
||||||
|
// other errors are fatal
|
||||||
|
return nil, readErr
|
||||||
|
}
|
||||||
|
if len(bytes.TrimSpace(doc)) == 0 {
|
||||||
|
// empty item, ignore
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// remember we attempted
|
||||||
|
attemptedItems++
|
||||||
|
pref, gvk, strictDecodeErr := strictCodecs.UniversalDecoder().Decode(doc, nil, nil)
|
||||||
|
if strictDecodeErr != nil {
|
||||||
|
var lenientDecodeErr error
|
||||||
|
pref, gvk, lenientDecodeErr = lenientCodecs.UniversalDecoder().Decode(doc, nil, nil)
|
||||||
|
if lenientDecodeErr != nil {
|
||||||
|
// both strict and lenient failed
|
||||||
|
// verbose log the error with the most information about this item and continue
|
||||||
|
klog.V(5).Infof("kuberc: strict decoding error for entry %d in %s: %v", attemptedItems, kubercFile, strictDecodeErr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check expected GVK, if bad, verbose log and continue
|
||||||
|
expectedGK := schema.GroupKind{
|
||||||
|
Group: config.SchemeGroupVersion.Group,
|
||||||
|
Kind: "Preference",
|
||||||
|
}
|
||||||
|
if gvk.GroupKind() != expectedGK {
|
||||||
|
klog.V(5).Infof("kuberc: unexpected GroupVersionKind for entry %d in %s: %v", attemptedItems, kubercFile, gvk)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// check expected go type, if bad, verbose log and continue
|
||||||
|
preferences, ok := pref.(*config.Preference)
|
||||||
|
if !ok {
|
||||||
|
klog.V(5).Infof("kuberc: unexpected object type %T for entry %d in %s", pref, attemptedItems, kubercFile)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// we have a usable preferences to return
|
||||||
|
klog.V(5).Infof("kuberc: successfully decoded entry %d in %s", attemptedItems, kubercFile)
|
||||||
|
return preferences, strictDecodeErr
|
||||||
|
|
||||||
|
}
|
||||||
|
if attemptedItems > 0 {
|
||||||
|
return nil, fmt.Errorf("no valid preferences found in %s, use --v=5 to see details", kubercFile)
|
||||||
|
}
|
||||||
|
// empty doc
|
||||||
|
klog.V(5).Infof("kuberc: no preferences found in %s", kubercFile)
|
||||||
|
return nil, nil
|
||||||
|
}
|
196
test/cmd/kuberc.sh
Executable file
196
test/cmd/kuberc.sh
Executable file
@ -0,0 +1,196 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright 2025 The Kubernetes 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
|
||||||
|
|
||||||
|
run_kuberc_tests() {
|
||||||
|
set -o nounset
|
||||||
|
set -o errexit
|
||||||
|
|
||||||
|
create_and_use_new_namespace
|
||||||
|
kube::log::status "Testing kuberc"
|
||||||
|
|
||||||
|
# Enable KUBERC feature
|
||||||
|
export KUBECTL_KUBERC=true
|
||||||
|
|
||||||
|
cat > "${TMPDIR:-/tmp}"/kuberc_file << EOF
|
||||||
|
apiVersion: kubectl.config.k8s.io/v1alpha1
|
||||||
|
kind: Preference
|
||||||
|
aliases:
|
||||||
|
- name: crns
|
||||||
|
command: create namespace
|
||||||
|
appendArgs:
|
||||||
|
- test-kuberc-ns
|
||||||
|
- name: getn
|
||||||
|
command: get
|
||||||
|
prependArgs:
|
||||||
|
- namespace
|
||||||
|
flags:
|
||||||
|
- name: output
|
||||||
|
default: wide
|
||||||
|
- name: crole
|
||||||
|
command: create role
|
||||||
|
flags:
|
||||||
|
- name: verb
|
||||||
|
default: get,watch
|
||||||
|
- name: getrole
|
||||||
|
command: get
|
||||||
|
flags:
|
||||||
|
- name: output
|
||||||
|
default: json
|
||||||
|
- name: runx
|
||||||
|
command: run
|
||||||
|
flags:
|
||||||
|
- name: image
|
||||||
|
default: nginx
|
||||||
|
- name: labels
|
||||||
|
default: app=test,env=test
|
||||||
|
- name: env
|
||||||
|
default: DNS_DOMAIN=test
|
||||||
|
- name: namespace
|
||||||
|
default: test-kuberc-ns
|
||||||
|
appendArgs:
|
||||||
|
- test-pod-2
|
||||||
|
- --
|
||||||
|
- custom-arg1
|
||||||
|
- custom-arg2
|
||||||
|
- name: setx
|
||||||
|
command: set image
|
||||||
|
appendArgs:
|
||||||
|
- pod/test-pod-2
|
||||||
|
- test-pod-2=busybox
|
||||||
|
overrides:
|
||||||
|
- command: apply
|
||||||
|
flags:
|
||||||
|
- name: server-side
|
||||||
|
default: "true"
|
||||||
|
- name: dry-run
|
||||||
|
default: "server"
|
||||||
|
- name: validate
|
||||||
|
default: "strict"
|
||||||
|
- command: delete
|
||||||
|
flags:
|
||||||
|
- name: interactive
|
||||||
|
default: "true"
|
||||||
|
- command: get
|
||||||
|
flags:
|
||||||
|
- name: namespace
|
||||||
|
default: "test-kuberc-ns"
|
||||||
|
- name: output
|
||||||
|
default: "json"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Pre-condition: the test-kuberc-ns namespace does not exist
|
||||||
|
kube::test::get_object_assert 'namespaces' "{{range.items}}{{ if eq ${id_field:?} \"test-kuberc-ns\" }}found{{end}}{{end}}:" ':'
|
||||||
|
# Alias command crns successfully creates namespace
|
||||||
|
kubectl crns --kuberc="${TMPDIR:-/tmp}"/kuberc_file
|
||||||
|
# Post-condition: namespace 'test-kuberc-ns' is created.
|
||||||
|
kube::test::get_object_assert 'namespaces/test-kuberc-ns' "{{$id_field}}" 'test-kuberc-ns'
|
||||||
|
|
||||||
|
# Alias command crns successfully creates namespace
|
||||||
|
kubectl getn --kuberc="${TMPDIR:-/tmp}"/kuberc_file test-kuberc-ns
|
||||||
|
# Post-condition: namespace 'test-kuberc-ns' is created.
|
||||||
|
kube::test::get_object_assert 'namespaces/test-kuberc-ns' "{{$id_field}}" 'test-kuberc-ns'
|
||||||
|
|
||||||
|
# Alias command crns successfully creates namespace
|
||||||
|
kubectl getn test-kuberc-ns --output=json --kuberc="${TMPDIR:-/tmp}"/kuberc_file
|
||||||
|
# Post-condition: namespace 'test-kuberc-ns' is created.
|
||||||
|
kube::test::get_object_assert 'namespaces/test-kuberc-ns' "{{$id_field}}" 'test-kuberc-ns'
|
||||||
|
|
||||||
|
# check array flags are appended after implicit defaults
|
||||||
|
kubectl crole testkubercrole --verb=list --namespace test-kuberc-ns --resource=pods --kuberc="${TMPDIR:-/tmp}"/kuberc_file
|
||||||
|
output_message=$(kubectl getrole role/testkubercrole -n test-kuberc-ns -oyaml --kuberc="${TMPDIR:-/tmp}"/kuberc_file)
|
||||||
|
kube::test::if_has_string "${output_message}" 'list'
|
||||||
|
kube::test::if_has_not_string "${output_message}" 'watch' 'get'
|
||||||
|
# Post-condition: remove role
|
||||||
|
kubectl delete role testkubercrole --namespace=test-kuberc-ns
|
||||||
|
|
||||||
|
# Alias run command creates a pod with the given configurations
|
||||||
|
kubectl runx --kuberc "${TMPDIR:-/tmp}"/kuberc_file
|
||||||
|
# Post-Condition: assertion object exists
|
||||||
|
kube::test::get_object_assert 'pod/test-pod-2 --namespace=test-kuberc-ns' "{{$id_field}}" 'test-pod-2'
|
||||||
|
# Not explicitly pass namespace to assure that default flag value is used
|
||||||
|
output_message=$(kubectl get pod/test-pod-2 2>&1 "${kube_flags[@]:?}" --kuberc="${TMPDIR:-/tmp}"/kuberc_file)
|
||||||
|
kube::test::if_has_string "${output_message}" 'nginx' 'app=test' 'env=test' 'DNS_DOMAIN=test' 'custom-arg1'
|
||||||
|
# output flag is defaulted to json and assure that it is correct format
|
||||||
|
kube::test::if_has_string "${output_message}" '{'
|
||||||
|
|
||||||
|
# pass explicit invalid namespace to assure that it takes precedence over the value in kuberc
|
||||||
|
output_message=$(! kubectl get pod/test-pod-2 -n kube-system 2>&1 "${kube_flags[@]:?}" --kuberc="${TMPDIR:-/tmp}"/kuberc_file)
|
||||||
|
kube::test::if_has_string "${output_message}" 'pods "test-pod-2" not found'
|
||||||
|
|
||||||
|
# Alias set env command sets new env var
|
||||||
|
kubectl setx --kuberc="${TMPDIR:-/tmp}"/kuberc_file -n test-kuberc-ns
|
||||||
|
# explicitly pass same namespace also defined in kuberc
|
||||||
|
output_message=$(kubectl get pod/test-pod-2 -n test-kuberc-ns 2>&1 "${kube_flags[@]:?}" --kuberc="${TMPDIR:-/tmp}"/kuberc_file)
|
||||||
|
kube::test::if_has_string "${output_message}" 'busybox'
|
||||||
|
kube::test::if_has_not_string "${output_message}" 'nginx'
|
||||||
|
|
||||||
|
# default overrides should prevent actual apply as they are all dry-run=server
|
||||||
|
# also assure that explicit flags are also passed
|
||||||
|
output_message=$(kubectl apply -n test-kuberc-ns -f hack/testdata/pod.yaml --kuberc="${TMPDIR:-/tmp}"/kuberc_file)
|
||||||
|
kube::test::if_has_string "${output_message}" 'serverside-applied (server dry run)'
|
||||||
|
|
||||||
|
# interactive flag is defaulted to true and prompted as no
|
||||||
|
output_message=$(kubectl delete pod/test-pod-2 -n test-kuberc-ns <<< $'n\n' --kuberc="${TMPDIR:-/tmp}"/kuberc_file)
|
||||||
|
kube::test::if_has_string "${output_message}" 'pod/test-pod-2'
|
||||||
|
# assure that it is not deleted
|
||||||
|
output_message=$(kubectl get pod/test-pod-2 2>&1 "${kube_flags[@]:?}" --kuberc="${TMPDIR:-/tmp}"/kuberc_file)
|
||||||
|
kube::test::if_has_string "${output_message}" "test-pod-2"
|
||||||
|
|
||||||
|
cat > "${TMPDIR:-/tmp}"/kuberc_file_multi << EOF
|
||||||
|
---
|
||||||
|
apiVersion: kubectl.config.k8s.io/v1alpha1
|
||||||
|
kind: Preference
|
||||||
|
overrides:
|
||||||
|
- command: get
|
||||||
|
flags:
|
||||||
|
- name: namespace
|
||||||
|
default: "test-kuberc-ns"
|
||||||
|
- name: output
|
||||||
|
default: "json"
|
||||||
|
unknown: invalid
|
||||||
|
---
|
||||||
|
apiVersion: kubectl.config.k8s.io/notexist
|
||||||
|
kind: Preference
|
||||||
|
overrides:
|
||||||
|
- command: get
|
||||||
|
flags:
|
||||||
|
- name: namespace
|
||||||
|
default: "test-kuberc-ns"
|
||||||
|
- name: output
|
||||||
|
default: "json"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# assure that it is not deleted
|
||||||
|
output_message=$(kubectl get pod/test-pod-2 2>&1 "${kube_flags[@]:?}" --kuberc="${TMPDIR:-/tmp}"/kuberc_file_multi)
|
||||||
|
# assure that correct kuberc is found and printed in output_message
|
||||||
|
kube::test::if_has_string "${output_message}" "test-pod-2"
|
||||||
|
# assure that warning message is also printed for the notexist kuberc version
|
||||||
|
kube::test::if_has_string "${output_message}" "strict decoding error" "unknown"
|
||||||
|
|
||||||
|
# explicitly overwriting the value that is also defaulted in kuberc and
|
||||||
|
# assure that explicit value supersedes
|
||||||
|
output_message=$(kubectl delete namespace/test-kuberc-ns --interactive=false --kuberc="${TMPDIR:-/tmp}"/kuberc_file)
|
||||||
|
kube::test::if_has_string "${output_message}" 'namespace "test-kuberc-ns" deleted'
|
||||||
|
|
||||||
|
unset KUBECTL_KUBERC
|
||||||
|
|
||||||
|
set +o nounset
|
||||||
|
set +o errexit
|
||||||
|
}
|
@ -48,6 +48,7 @@ source "${KUBE_ROOT}/test/cmd/generic-resources.sh"
|
|||||||
source "${KUBE_ROOT}/test/cmd/get.sh"
|
source "${KUBE_ROOT}/test/cmd/get.sh"
|
||||||
source "${KUBE_ROOT}/test/cmd/help.sh"
|
source "${KUBE_ROOT}/test/cmd/help.sh"
|
||||||
source "${KUBE_ROOT}/test/cmd/kubeconfig.sh"
|
source "${KUBE_ROOT}/test/cmd/kubeconfig.sh"
|
||||||
|
source "${KUBE_ROOT}/test/cmd/kuberc.sh"
|
||||||
source "${KUBE_ROOT}/test/cmd/node-management.sh"
|
source "${KUBE_ROOT}/test/cmd/node-management.sh"
|
||||||
source "${KUBE_ROOT}/test/cmd/plugins.sh"
|
source "${KUBE_ROOT}/test/cmd/plugins.sh"
|
||||||
source "${KUBE_ROOT}/test/cmd/proxy.sh"
|
source "${KUBE_ROOT}/test/cmd/proxy.sh"
|
||||||
@ -1056,5 +1057,11 @@ runTests() {
|
|||||||
record_command run_kubectl_debug_netadmin_node_tests
|
record_command run_kubectl_debug_netadmin_node_tests
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# kuberc #
|
||||||
|
#######################
|
||||||
|
|
||||||
|
record_command run_kuberc_tests
|
||||||
|
|
||||||
cleanup_tests
|
cleanup_tests
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user