Revert "Revert "Add optional validation to kubecfg/kubectl.""

This reverts commit 6590c66dd4.
This commit is contained in:
Brendan Burns
2014-11-25 19:50:31 -08:00
parent 7f2d0c0f71
commit c29f5db81c
9 changed files with 106 additions and 19 deletions

View File

@@ -24,6 +24,8 @@ 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/client/clientcmd"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
@@ -41,6 +43,7 @@ type Factory struct {
Client func(cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.RESTClient, 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)
Validator func(*cobra.Command) (validation.Schema, error)
}
// NewFactory creates a factory with the default Kubernetes resources defined
@@ -49,6 +52,13 @@ func NewFactory(clientBuilder clientcmd.Builder) *Factory {
ClientBuilder: clientBuilder,
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 clientBuilder.Client()
},
@@ -88,6 +98,7 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`,
// 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().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.NewCmdProxy(out))

View File

@@ -43,7 +43,9 @@ Examples:
if len(filename) == 0 {
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)
checkErr(err)

View File

@@ -50,7 +50,9 @@ Examples:
<delete a pod with ID 1234-56-7890-234234-456456>`,
Run: func(cmd *cobra.Command, args []string) {
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)
checkErr(err)

View File

@@ -20,6 +20,7 @@ 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"
@@ -29,7 +30,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) (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 len(args) > 0 && len(args) != 2 {
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")
}
mapping, namespace, name, _ = ResourceFromFile(filename, typer, mapper)
mapping, namespace, name, _ = ResourceFromFile(filename, typer, mapper, schema)
if len(name) == 0 {
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
// 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) (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)
checkErr(err)
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"))
}
err = schema.ValidateBytes(data)
checkErr(err)
mapping, err = mapper.RESTMapping(version, kind)
checkErr(err)

View File

@@ -43,7 +43,9 @@ Examples:
if len(filename) == 0 {
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)
checkErr(err)