mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 11:48:15 +00:00 
			
		
		
		
	Revert "Revert "Add optional validation to kubecfg/kubectl.""
This reverts commit 6590c66dd4.
			
			
This commit is contained in:
		@@ -152,12 +152,18 @@ func readConfigData() []byte {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// readConfig reads and parses pod, replicationController, and service
 | 
					// readConfig reads and parses pod, replicationController, and service
 | 
				
			||||||
// configuration files. If any errors log and exit non-zero.
 | 
					// configuration files. If any errors log and exit non-zero.
 | 
				
			||||||
func readConfig(storage string, serverCodec runtime.Codec) []byte {
 | 
					func readConfig(storage string, c *client.Client) []byte {
 | 
				
			||||||
 | 
						serverCodec := c.RESTClient.Codec
 | 
				
			||||||
	if len(*config) == 0 {
 | 
						if len(*config) == 0 {
 | 
				
			||||||
		glog.Fatal("Need config file (-c)")
 | 
							glog.Fatal("Need config file (-c)")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data, err := parser.ToWireFormat(readConfigData(), storage, latest.Codec, serverCodec)
 | 
						dataInput := readConfigData()
 | 
				
			||||||
 | 
						err := kubecfg.ValidateObject(dataInput, c)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							glog.Fatalf("Error validating %v as an object for %v: %v\n", *config, storage, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						data, err := parser.ToWireFormat(dataInput, storage, latest.Codec, serverCodec)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		glog.Fatalf("Error parsing %v as an object for %v: %v\n", *config, storage, err)
 | 
							glog.Fatalf("Error parsing %v as an object for %v: %v\n", *config, storage, err)
 | 
				
			||||||
@@ -383,7 +389,7 @@ func executeAPIRequest(ctx api.Context, method string, c *client.Client) bool {
 | 
				
			|||||||
			glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>/<id>", method, prettyWireStorage())
 | 
								glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>/<id>", method, prettyWireStorage())
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case "print":
 | 
						case "print":
 | 
				
			||||||
		data := readConfig(storage, c.RESTClient.Codec)
 | 
							data := readConfig(storage, c)
 | 
				
			||||||
		obj, err := latest.Codec.Decode(data)
 | 
							obj, err := latest.Codec.Decode(data)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			glog.Fatalf("error setting resource version: %v", err)
 | 
								glog.Fatalf("error setting resource version: %v", err)
 | 
				
			||||||
@@ -403,7 +409,7 @@ func executeAPIRequest(ctx api.Context, method string, c *client.Client) bool {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	if setBody {
 | 
						if setBody {
 | 
				
			||||||
		if len(version) > 0 {
 | 
							if len(version) > 0 {
 | 
				
			||||||
			data := readConfig(storage, c.RESTClient.Codec)
 | 
								data := readConfig(storage, c)
 | 
				
			||||||
			obj, err := latest.Codec.Decode(data)
 | 
								obj, err := latest.Codec.Decode(data)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				glog.Fatalf("error setting resource version: %v", err)
 | 
									glog.Fatalf("error setting resource version: %v", err)
 | 
				
			||||||
@@ -419,7 +425,7 @@ func executeAPIRequest(ctx api.Context, method string, c *client.Client) bool {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			r.Body(data)
 | 
								r.Body(data)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			r.Body(readConfig(storage, c.RESTClient.Codec))
 | 
								r.Body(readConfig(storage, c))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	result := r.Do()
 | 
						result := r.Do()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,12 +40,21 @@ func NewInvalidTypeError(expected reflect.Kind, observed reflect.Kind, fieldName
 | 
				
			|||||||
	return &InvalidTypeError{expected, observed, fieldName}
 | 
						return &InvalidTypeError{expected, observed, fieldName}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Schema struct {
 | 
					// Schema is an interface that knows how to validate an API object serialized to a byte array.
 | 
				
			||||||
 | 
					type Schema interface {
 | 
				
			||||||
 | 
						ValidateBytes(data []byte) error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type NullSchema struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (NullSchema) ValidateBytes(data []byte) error { return nil }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SwaggerSchema struct {
 | 
				
			||||||
	api swagger.ApiDeclaration
 | 
						api swagger.ApiDeclaration
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewSchemaFromBytes(data []byte) (*Schema, error) {
 | 
					func NewSwaggerSchemaFromBytes(data []byte) (Schema, error) {
 | 
				
			||||||
	schema := &Schema{}
 | 
						schema := &SwaggerSchema{}
 | 
				
			||||||
	err := json.Unmarshal(data, &schema.api)
 | 
						err := json.Unmarshal(data, &schema.api)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@@ -53,7 +62,7 @@ func NewSchemaFromBytes(data []byte) (*Schema, error) {
 | 
				
			|||||||
	return schema, nil
 | 
						return schema, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *Schema) ValidateBytes(data []byte) error {
 | 
					func (s *SwaggerSchema) ValidateBytes(data []byte) error {
 | 
				
			||||||
	var obj interface{}
 | 
						var obj interface{}
 | 
				
			||||||
	err := json.Unmarshal(data, &obj)
 | 
						err := json.Unmarshal(data, &obj)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -65,7 +74,7 @@ func (s *Schema) ValidateBytes(data []byte) error {
 | 
				
			|||||||
	return s.ValidateObject(obj, apiVersion, "", apiVersion+"."+kind)
 | 
						return s.ValidateObject(obj, apiVersion, "", apiVersion+"."+kind)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *Schema) ValidateObject(obj interface{}, apiVersion, fieldName, typeName string) error {
 | 
					func (s *SwaggerSchema) ValidateObject(obj interface{}, apiVersion, fieldName, typeName string) error {
 | 
				
			||||||
	models := s.api.Models
 | 
						models := s.api.Models
 | 
				
			||||||
	// TODO: handle required fields here too.
 | 
						// TODO: handle required fields here too.
 | 
				
			||||||
	model, ok := models[typeName]
 | 
						model, ok := models[typeName]
 | 
				
			||||||
@@ -98,7 +107,7 @@ func (s *Schema) ValidateObject(obj interface{}, apiVersion, fieldName, typeName
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *Schema) validateField(value interface{}, apiVersion, fieldName, fieldType string, fieldDetails *swagger.ModelProperty) error {
 | 
					func (s *SwaggerSchema) validateField(value interface{}, apiVersion, fieldName, fieldType string, fieldDetails *swagger.ModelProperty) error {
 | 
				
			||||||
	if strings.HasPrefix(fieldType, apiVersion) {
 | 
						if strings.HasPrefix(fieldType, apiVersion) {
 | 
				
			||||||
		return s.ValidateObject(value, apiVersion, fieldName, fieldType)
 | 
							return s.ValidateObject(value, apiVersion, fieldName, fieldType)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,12 +30,12 @@ import (
 | 
				
			|||||||
	fuzz "github.com/google/gofuzz"
 | 
						fuzz "github.com/google/gofuzz"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func LoadSchemaForTest(file string) (*Schema, error) {
 | 
					func LoadSchemaForTest(file string) (Schema, error) {
 | 
				
			||||||
	data, err := ioutil.ReadFile(file)
 | 
						data, err := ioutil.ReadFile(file)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return NewSchemaFromBytes(data)
 | 
						return NewSwaggerSchemaFromBytes(data)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: this is cloned from serialization_test.go, refactor to somewhere common like util
 | 
					// TODO: this is cloned from serialization_test.go, refactor to somewhere common like util
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										51
									
								
								pkg/kubecfg/validate.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								pkg/kubecfg/validate.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2014 Google Inc. All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 kubecfg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidateObject(data []byte, c *client.Client) error {
 | 
				
			||||||
 | 
						var obj interface{}
 | 
				
			||||||
 | 
						err := json.Unmarshal(data, &obj)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						apiVersion, found := obj.(map[string]interface{})["apiVersion"]
 | 
				
			||||||
 | 
						if !found {
 | 
				
			||||||
 | 
							return fmt.Errorf("couldn't find apiVersion in object")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						schemaData, err := c.RESTClient.Get().
 | 
				
			||||||
 | 
							AbsPath("/swaggerapi/api").
 | 
				
			||||||
 | 
							Path(apiVersion.(string)).
 | 
				
			||||||
 | 
							Do().
 | 
				
			||||||
 | 
							Raw()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						schema, err := validation.NewSwaggerSchemaFromBytes(schemaData)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return schema.ValidateBytes(data)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -24,6 +24,8 @@ import (
 | 
				
			|||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
				
			||||||
@@ -41,6 +43,7 @@ type Factory struct {
 | 
				
			|||||||
	Client        func(cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.RESTClient, error)
 | 
						Client        func(cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.RESTClient, error)
 | 
				
			||||||
	Describer     func(cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.Describer, error)
 | 
						Describer     func(cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.Describer, error)
 | 
				
			||||||
	Printer       func(cmd *cobra.Command, mapping *meta.RESTMapping, noHeaders bool) (kubectl.ResourcePrinter, error)
 | 
						Printer       func(cmd *cobra.Command, mapping *meta.RESTMapping, noHeaders bool) (kubectl.ResourcePrinter, error)
 | 
				
			||||||
 | 
						Validator     func(*cobra.Command) (validation.Schema, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewFactory creates a factory with the default Kubernetes resources defined
 | 
					// NewFactory creates a factory with the default Kubernetes resources defined
 | 
				
			||||||
@@ -49,6 +52,13 @@ func NewFactory(clientBuilder clientcmd.Builder) *Factory {
 | 
				
			|||||||
		ClientBuilder: clientBuilder,
 | 
							ClientBuilder: clientBuilder,
 | 
				
			||||||
		Mapper:        latest.RESTMapper,
 | 
							Mapper:        latest.RESTMapper,
 | 
				
			||||||
		Typer:         api.Scheme,
 | 
							Typer:         api.Scheme,
 | 
				
			||||||
 | 
							Validator:     func(cmd *cobra.Command) (validation.Schema, error) {
 | 
				
			||||||
 | 
								if GetFlagBool(cmd, "validate") {
 | 
				
			||||||
 | 
									return &clientSwaggerSchema{getKubeClient(cmd), api.Scheme}, nil
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									return validation.NullSchema{}, nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		Client: func(cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.RESTClient, error) {
 | 
							Client: func(cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.RESTClient, error) {
 | 
				
			||||||
			return clientBuilder.Client()
 | 
								return clientBuilder.Client()
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -88,6 +98,7 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`,
 | 
				
			|||||||
	// to do that automatically for every subcommand.
 | 
						// to do that automatically for every subcommand.
 | 
				
			||||||
	cmds.PersistentFlags().String("ns-path", os.Getenv("HOME")+"/.kubernetes_ns", "Path to the namespace info file that holds the namespace context to use for CLI requests.")
 | 
						cmds.PersistentFlags().String("ns-path", os.Getenv("HOME")+"/.kubernetes_ns", "Path to the namespace info file that holds the namespace context to use for CLI requests.")
 | 
				
			||||||
	cmds.PersistentFlags().StringP("namespace", "n", "", "If present, the namespace scope for this CLI request.")
 | 
						cmds.PersistentFlags().StringP("namespace", "n", "", "If present, the namespace scope for this CLI request.")
 | 
				
			||||||
 | 
						cmds.PersistentFlags().Bool("validate", false, "If true, use a schema to validate the input before sending it")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmds.AddCommand(f.NewCmdVersion(out))
 | 
						cmds.AddCommand(f.NewCmdVersion(out))
 | 
				
			||||||
	cmds.AddCommand(f.NewCmdProxy(out))
 | 
						cmds.AddCommand(f.NewCmdProxy(out))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,7 +43,9 @@ Examples:
 | 
				
			|||||||
			if len(filename) == 0 {
 | 
								if len(filename) == 0 {
 | 
				
			||||||
				usageError(cmd, "Must specify filename to create")
 | 
									usageError(cmd, "Must specify filename to create")
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			mapping, namespace, name, data := ResourceFromFile(filename, f.Typer, f.Mapper)
 | 
								schema, err := f.Validator(cmd)
 | 
				
			||||||
 | 
								checkErr(err)
 | 
				
			||||||
 | 
								mapping, namespace, name, data := ResourceFromFile(filename, f.Typer, f.Mapper, schema)
 | 
				
			||||||
			client, err := f.Client(cmd, mapping)
 | 
								client, err := f.Client(cmd, mapping)
 | 
				
			||||||
			checkErr(err)
 | 
								checkErr(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,7 +50,9 @@ Examples:
 | 
				
			|||||||
  <delete a pod with ID 1234-56-7890-234234-456456>`,
 | 
					  <delete a pod with ID 1234-56-7890-234234-456456>`,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			filename := GetFlagString(cmd, "filename")
 | 
								filename := GetFlagString(cmd, "filename")
 | 
				
			||||||
			mapping, namespace, name := ResourceFromArgsOrFile(cmd, args, filename, f.Typer, f.Mapper)
 | 
								schema, err := f.Validator(cmd)
 | 
				
			||||||
 | 
								checkErr(err)
 | 
				
			||||||
 | 
								mapping, namespace, name := ResourceFromArgsOrFile(cmd, args, filename, f.Typer, f.Mapper, schema)
 | 
				
			||||||
			client, err := f.Client(cmd, mapping)
 | 
								client, err := f.Client(cmd, mapping)
 | 
				
			||||||
			checkErr(err)
 | 
								checkErr(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,7 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -29,7 +30,7 @@ import (
 | 
				
			|||||||
// ResourceFromArgsOrFile expects two arguments or a valid file with a given type, and extracts
 | 
					// ResourceFromArgsOrFile expects two arguments or a valid file with a given type, and extracts
 | 
				
			||||||
// the fields necessary to uniquely locate a resource. Displays a usageError if that contract is
 | 
					// the fields necessary to uniquely locate a resource. Displays a usageError if that contract is
 | 
				
			||||||
// not satisfied, or a generic error if any other problems occur.
 | 
					// not satisfied, or a generic error if any other problems occur.
 | 
				
			||||||
func ResourceFromArgsOrFile(cmd *cobra.Command, args []string, filename string, typer runtime.ObjectTyper, mapper meta.RESTMapper) (mapping *meta.RESTMapping, namespace, name string) {
 | 
					func ResourceFromArgsOrFile(cmd *cobra.Command, args []string, filename string, typer runtime.ObjectTyper, mapper meta.RESTMapper, schema validation.Schema) (mapping *meta.RESTMapping, namespace, name string) {
 | 
				
			||||||
	// If command line args are passed in, use those preferentially.
 | 
						// If command line args are passed in, use those preferentially.
 | 
				
			||||||
	if len(args) > 0 && len(args) != 2 {
 | 
						if len(args) > 0 && len(args) != 2 {
 | 
				
			||||||
		usageError(cmd, "If passing in command line parameters, must be resource and name")
 | 
							usageError(cmd, "If passing in command line parameters, must be resource and name")
 | 
				
			||||||
@@ -58,7 +59,7 @@ func ResourceFromArgsOrFile(cmd *cobra.Command, args []string, filename string,
 | 
				
			|||||||
		usageError(cmd, "Must specify filename or command line params")
 | 
							usageError(cmd, "Must specify filename or command line params")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mapping, namespace, name, _ = ResourceFromFile(filename, typer, mapper)
 | 
						mapping, namespace, name, _ = ResourceFromFile(filename, typer, mapper, schema)
 | 
				
			||||||
	if len(name) == 0 {
 | 
						if len(name) == 0 {
 | 
				
			||||||
		checkErr(fmt.Errorf("the resource in the provided file has no name (or ID) defined"))
 | 
							checkErr(fmt.Errorf("the resource in the provided file has no name (or ID) defined"))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -122,7 +123,7 @@ func ResourceOrTypeFromArgs(cmd *cobra.Command, args []string, mapper meta.RESTM
 | 
				
			|||||||
// ResourceFromFile retrieves the name and namespace from a valid file. If the file does not
 | 
					// ResourceFromFile retrieves the name and namespace from a valid file. If the file does not
 | 
				
			||||||
// resolve to a known type an error is returned. The returned mapping can be used to determine
 | 
					// resolve to a known type an error is returned. The returned mapping can be used to determine
 | 
				
			||||||
// the correct REST endpoint to modify this resource with.
 | 
					// the correct REST endpoint to modify this resource with.
 | 
				
			||||||
func ResourceFromFile(filename string, typer runtime.ObjectTyper, mapper meta.RESTMapper) (mapping *meta.RESTMapping, namespace, name string, data []byte) {
 | 
					func ResourceFromFile(filename string, typer runtime.ObjectTyper, mapper meta.RESTMapper, schema validation.Schema) (mapping *meta.RESTMapping, namespace, name string, data []byte) {
 | 
				
			||||||
	configData, err := ReadConfigData(filename)
 | 
						configData, err := ReadConfigData(filename)
 | 
				
			||||||
	checkErr(err)
 | 
						checkErr(err)
 | 
				
			||||||
	data = configData
 | 
						data = configData
 | 
				
			||||||
@@ -135,6 +136,9 @@ func ResourceFromFile(filename string, typer runtime.ObjectTyper, mapper meta.RE
 | 
				
			|||||||
		checkErr(fmt.Errorf("the resource in the provided file has no apiVersion defined"))
 | 
							checkErr(fmt.Errorf("the resource in the provided file has no apiVersion defined"))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = schema.ValidateBytes(data)
 | 
				
			||||||
 | 
						checkErr(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mapping, err = mapper.RESTMapping(version, kind)
 | 
						mapping, err = mapper.RESTMapping(version, kind)
 | 
				
			||||||
	checkErr(err)
 | 
						checkErr(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,7 +43,9 @@ Examples:
 | 
				
			|||||||
			if len(filename) == 0 {
 | 
								if len(filename) == 0 {
 | 
				
			||||||
				usageError(cmd, "Must specify filename to update")
 | 
									usageError(cmd, "Must specify filename to update")
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			mapping, namespace, name, data := ResourceFromFile(filename, f.Typer, f.Mapper)
 | 
								schema, err := f.Validator(cmd)
 | 
				
			||||||
 | 
								checkErr(err)
 | 
				
			||||||
 | 
								mapping, namespace, name, data := ResourceFromFile(filename, f.Typer, f.Mapper, schema)
 | 
				
			||||||
			client, err := f.Client(cmd, mapping)
 | 
								client, err := f.Client(cmd, mapping)
 | 
				
			||||||
			checkErr(err)
 | 
								checkErr(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user