mirror of https://github.com/k3s-io/k3s
parent
f5f5542bb2
commit
6590c66dd4
|
@ -152,18 +152,12 @@ func readConfigData() []byte {
|
|||
|
||||
// readConfig reads and parses pod, replicationController, and service
|
||||
// configuration files. If any errors log and exit non-zero.
|
||||
func readConfig(storage string, c *client.Client) []byte {
|
||||
serverCodec := c.RESTClient.Codec
|
||||
func readConfig(storage string, serverCodec runtime.Codec) []byte {
|
||||
if len(*config) == 0 {
|
||||
glog.Fatal("Need config file (-c)")
|
||||
}
|
||||
|
||||
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)
|
||||
data, err := parser.ToWireFormat(readConfigData(), storage, latest.Codec, serverCodec)
|
||||
|
||||
if err != nil {
|
||||
glog.Fatalf("Error parsing %v as an object for %v: %v\n", *config, storage, err)
|
||||
|
@ -389,7 +383,7 @@ func executeAPIRequest(ctx api.Context, method string, c *client.Client) bool {
|
|||
glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>/<id>", method, prettyWireStorage())
|
||||
}
|
||||
case "print":
|
||||
data := readConfig(storage, c)
|
||||
data := readConfig(storage, c.RESTClient.Codec)
|
||||
obj, err := latest.Codec.Decode(data)
|
||||
if err != nil {
|
||||
glog.Fatalf("error setting resource version: %v", err)
|
||||
|
@ -409,7 +403,7 @@ func executeAPIRequest(ctx api.Context, method string, c *client.Client) bool {
|
|||
}
|
||||
if setBody {
|
||||
if len(version) > 0 {
|
||||
data := readConfig(storage, c)
|
||||
data := readConfig(storage, c.RESTClient.Codec)
|
||||
obj, err := latest.Codec.Decode(data)
|
||||
if err != nil {
|
||||
glog.Fatalf("error setting resource version: %v", err)
|
||||
|
@ -425,7 +419,7 @@ func executeAPIRequest(ctx api.Context, method string, c *client.Client) bool {
|
|||
}
|
||||
r.Body(data)
|
||||
} else {
|
||||
r.Body(readConfig(storage, c))
|
||||
r.Body(readConfig(storage, c.RESTClient.Codec))
|
||||
}
|
||||
}
|
||||
result := r.Do()
|
||||
|
|
|
@ -40,21 +40,12 @@ func NewInvalidTypeError(expected reflect.Kind, observed reflect.Kind, fieldName
|
|||
return &InvalidTypeError{expected, observed, fieldName}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
type Schema struct {
|
||||
api swagger.ApiDeclaration
|
||||
}
|
||||
|
||||
func NewSwaggerSchemaFromBytes(data []byte) (Schema, error) {
|
||||
schema := &SwaggerSchema{}
|
||||
func NewSchemaFromBytes(data []byte) (*Schema, error) {
|
||||
schema := &Schema{}
|
||||
err := json.Unmarshal(data, &schema.api)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -62,7 +53,7 @@ func NewSwaggerSchemaFromBytes(data []byte) (Schema, error) {
|
|||
return schema, nil
|
||||
}
|
||||
|
||||
func (s *SwaggerSchema) ValidateBytes(data []byte) error {
|
||||
func (s *Schema) ValidateBytes(data []byte) error {
|
||||
var obj interface{}
|
||||
err := json.Unmarshal(data, &obj)
|
||||
if err != nil {
|
||||
|
@ -74,7 +65,7 @@ func (s *SwaggerSchema) ValidateBytes(data []byte) error {
|
|||
return s.ValidateObject(obj, apiVersion, "", apiVersion+"."+kind)
|
||||
}
|
||||
|
||||
func (s *SwaggerSchema) ValidateObject(obj interface{}, apiVersion, fieldName, typeName string) error {
|
||||
func (s *Schema) ValidateObject(obj interface{}, apiVersion, fieldName, typeName string) error {
|
||||
models := s.api.Models
|
||||
// TODO: handle required fields here too.
|
||||
model, ok := models[typeName]
|
||||
|
@ -107,7 +98,7 @@ func (s *SwaggerSchema) ValidateObject(obj interface{}, apiVersion, fieldName, t
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *SwaggerSchema) validateField(value interface{}, apiVersion, fieldName, fieldType string, fieldDetails *swagger.ModelProperty) error {
|
||||
func (s *Schema) validateField(value interface{}, apiVersion, fieldName, fieldType string, fieldDetails *swagger.ModelProperty) error {
|
||||
if strings.HasPrefix(fieldType, apiVersion) {
|
||||
return s.ValidateObject(value, apiVersion, fieldName, fieldType)
|
||||
}
|
||||
|
|
|
@ -30,12 +30,12 @@ import (
|
|||
fuzz "github.com/google/gofuzz"
|
||||
)
|
||||
|
||||
func LoadSchemaForTest(file string) (Schema, error) {
|
||||
func LoadSchemaForTest(file string) (*Schema, error) {
|
||||
data, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewSwaggerSchemaFromBytes(data)
|
||||
return NewSchemaFromBytes(data)
|
||||
}
|
||||
|
||||
// TODO: this is cloned from serialization_test.go, refactor to somewhere common like util
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
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,7 +24,6 @@ import (
|
|||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
|
||||
"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/kubectl"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
|
@ -37,7 +36,6 @@ import (
|
|||
type Factory struct {
|
||||
Mapper meta.RESTMapper
|
||||
Typer runtime.ObjectTyper
|
||||
Validator func(*cobra.Command) (validation.Schema, error)
|
||||
Client func(*cobra.Command, *meta.RESTMapping) (kubectl.RESTClient, error)
|
||||
Describer func(*cobra.Command, *meta.RESTMapping) (kubectl.Describer, error)
|
||||
Printer func(cmd *cobra.Command, mapping *meta.RESTMapping, noHeaders bool) (kubectl.ResourcePrinter, error)
|
||||
|
@ -48,13 +46,6 @@ func NewFactory() *Factory {
|
|||
return &Factory{
|
||||
Mapper: latest.RESTMapper,
|
||||
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) {
|
||||
return getKubeClient(cmd), nil
|
||||
},
|
||||
|
@ -96,7 +87,6 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`,
|
|||
cmds.PersistentFlags().Bool("insecure-skip-tls-verify", false, "If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.")
|
||||
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().Bool("validate", false, "If true, use a schema to validate the input before sending it")
|
||||
|
||||
cmds.AddCommand(NewCmdVersion(out))
|
||||
cmds.AddCommand(NewCmdProxy(out))
|
||||
|
@ -226,28 +216,3 @@ func getKubeClient(cmd *cobra.Command) *client.Client {
|
|||
}
|
||||
return c
|
||||
}
|
||||
|
||||
type clientSwaggerSchema struct {
|
||||
c *client.Client
|
||||
t runtime.ObjectTyper
|
||||
}
|
||||
|
||||
func (c *clientSwaggerSchema) ValidateBytes(data []byte) error {
|
||||
version, _, err := c.t.DataVersionAndKind(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
schemaData, err := c.c.RESTClient.Get().
|
||||
AbsPath("/swaggerapi/api").
|
||||
Path(version).
|
||||
Do().
|
||||
Raw()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
schema, err := validation.NewSwaggerSchemaFromBytes(schemaData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return schema.ValidateBytes(data)
|
||||
}
|
||||
|
|
|
@ -43,9 +43,7 @@ Examples:
|
|||
if len(filename) == 0 {
|
||||
usageError(cmd, "Must specify filename to create")
|
||||
}
|
||||
schema, err := f.Validator(cmd)
|
||||
checkErr(err)
|
||||
mapping, namespace, name, data := ResourceFromFile(filename, f.Typer, f.Mapper, schema)
|
||||
mapping, namespace, name, data := ResourceFromFile(filename, f.Typer, f.Mapper)
|
||||
client, err := f.Client(cmd, mapping)
|
||||
checkErr(err)
|
||||
|
||||
|
|
|
@ -50,9 +50,7 @@ Examples:
|
|||
<delete a pod with ID 1234-56-7890-234234-456456>`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
filename := GetFlagString(cmd, "filename")
|
||||
schema, err := f.Validator(cmd)
|
||||
checkErr(err)
|
||||
mapping, namespace, name := ResourceFromArgsOrFile(cmd, args, filename, f.Typer, f.Mapper, schema)
|
||||
mapping, namespace, name := ResourceFromArgsOrFile(cmd, args, filename, f.Typer, f.Mapper)
|
||||
client, err := f.Client(cmd, mapping)
|
||||
checkErr(err)
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ import (
|
|||
"fmt"
|
||||
|
||||
"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/runtime"
|
||||
|
||||
|
@ -30,7 +29,7 @@ import (
|
|||
// 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
|
||||
// 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, schema validation.Schema) (mapping *meta.RESTMapping, namespace, name string) {
|
||||
func ResourceFromArgsOrFile(cmd *cobra.Command, args []string, filename string, typer runtime.ObjectTyper, mapper meta.RESTMapper) (mapping *meta.RESTMapping, namespace, name string) {
|
||||
// If command line args are passed in, use those preferentially.
|
||||
if len(args) > 0 && len(args) != 2 {
|
||||
usageError(cmd, "If passing in command line parameters, must be resource and name")
|
||||
|
@ -59,7 +58,7 @@ func ResourceFromArgsOrFile(cmd *cobra.Command, args []string, filename string,
|
|||
usageError(cmd, "Must specify filename or command line params")
|
||||
}
|
||||
|
||||
mapping, namespace, name, _ = ResourceFromFile(filename, typer, mapper, schema)
|
||||
mapping, namespace, name, _ = ResourceFromFile(filename, typer, mapper)
|
||||
if len(name) == 0 {
|
||||
checkErr(fmt.Errorf("the resource in the provided file has no name (or ID) defined"))
|
||||
}
|
||||
|
@ -123,7 +122,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
|
||||
// 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.
|
||||
func ResourceFromFile(filename string, typer runtime.ObjectTyper, mapper meta.RESTMapper, schema validation.Schema) (mapping *meta.RESTMapping, namespace, name string, data []byte) {
|
||||
func ResourceFromFile(filename string, typer runtime.ObjectTyper, mapper meta.RESTMapper) (mapping *meta.RESTMapping, namespace, name string, data []byte) {
|
||||
configData, err := ReadConfigData(filename)
|
||||
checkErr(err)
|
||||
data = configData
|
||||
|
@ -136,9 +135,6 @@ func ResourceFromFile(filename string, typer runtime.ObjectTyper, mapper meta.RE
|
|||
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)
|
||||
checkErr(err)
|
||||
|
||||
|
|
|
@ -43,9 +43,7 @@ Examples:
|
|||
if len(filename) == 0 {
|
||||
usageError(cmd, "Must specify filename to update")
|
||||
}
|
||||
schema, err := f.Validator(cmd)
|
||||
checkErr(err)
|
||||
mapping, namespace, name, data := ResourceFromFile(filename, f.Typer, f.Mapper, schema)
|
||||
mapping, namespace, name, data := ResourceFromFile(filename, f.Typer, f.Mapper)
|
||||
client, err := f.Client(cmd, mapping)
|
||||
checkErr(err)
|
||||
|
||||
|
|
Loading…
Reference in New Issue