mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-10-30 17:58:14 +00:00 
			
		
		
		
	Introduce kuberc as new flag to customize defaulting and define aliases in kubectl (#125230)
This commit is contained in:
		
							
								
								
									
										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 | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Arda Güçlü
					Arda Güçlü