mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 03:41:45 +00:00
add kubectl create --raw -f
This commit is contained in:
parent
060b4b8b84
commit
58f39a15de
@ -936,6 +936,9 @@ run_create_tests() {
|
||||
# Post-condition: jsonpath for .metadata.namespace should be empty for object since --namespace was not explicitly specified
|
||||
kube::test::if_empty_string "${output_message}"
|
||||
|
||||
kubectl create configmap tester-create-cm -o json --dry-run | kubectl create "${kube_flags[@]}" --raw /api/v1/namespaces/default/configmaps -f -
|
||||
kubectl delete -ndefault "${kube_flags[@]}" configmap tester-create-cm
|
||||
|
||||
set +o nounset
|
||||
set +o errexit
|
||||
}
|
||||
@ -3674,6 +3677,11 @@ run_kubectl_create_error_tests() {
|
||||
fi
|
||||
rm "${ERROR_FILE}"
|
||||
|
||||
# Posting a pod to namespaces should fail. Also tests --raw forcing the post location
|
||||
[ "$( kubectl convert -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml -o json | kubectl create "${kube_flags[@]}" --raw /api/v1/namespaces -f - --v=8 2>&1 | grep 'cannot be handled as a Namespace: converting (v1.Pod)')" ]
|
||||
|
||||
[ "$( kubectl create "${kube_flags[@]}" --raw /api/v1/namespaces -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml --edit 2>&1 | grep 'raw and --edit are mutually exclusive')" ]
|
||||
|
||||
set +o nounset
|
||||
set +o errexit
|
||||
}
|
||||
|
@ -19,13 +19,16 @@ package cmd
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"net/url"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
@ -38,6 +41,7 @@ type CreateOptions struct {
|
||||
FilenameOptions resource.FilenameOptions
|
||||
Selector string
|
||||
EditBeforeCreate bool
|
||||
Raw string
|
||||
}
|
||||
|
||||
var (
|
||||
@ -71,7 +75,7 @@ func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
|
||||
defaultRunFunc(cmd, args)
|
||||
return
|
||||
}
|
||||
cmdutil.CheckErr(ValidateArgs(cmd, args))
|
||||
cmdutil.CheckErr(options.ValidateArgs(cmd, args))
|
||||
cmdutil.CheckErr(RunCreate(f, cmd, out, errOut, &options))
|
||||
},
|
||||
}
|
||||
@ -89,6 +93,7 @@ func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
|
||||
cmdutil.AddDryRunFlag(cmd)
|
||||
cmdutil.AddInclude3rdPartyFlags(cmd)
|
||||
cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
|
||||
cmd.Flags().StringVar(&options.Raw, "raw", options.Raw, "Raw URI to POST to the server. Uses the transport specified by the kubeconfig file.")
|
||||
|
||||
// create subcommands
|
||||
cmd.AddCommand(NewCmdCreateNamespace(f, out))
|
||||
@ -106,14 +111,65 @@ func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func ValidateArgs(cmd *cobra.Command, args []string) error {
|
||||
func (o *CreateOptions) ValidateArgs(cmd *cobra.Command, args []string) error {
|
||||
if len(args) != 0 {
|
||||
return cmdutil.UsageErrorf(cmd, "Unexpected args: %v", args)
|
||||
}
|
||||
if len(o.Raw) > 0 {
|
||||
if o.EditBeforeCreate {
|
||||
return cmdutil.UsageErrorf(cmd, "--raw and --edit are mutually exclusive")
|
||||
}
|
||||
if len(o.FilenameOptions.Filenames) != 1 {
|
||||
return cmdutil.UsageErrorf(cmd, "--raw can only use a single local file or stdin")
|
||||
}
|
||||
if strings.HasPrefix(o.FilenameOptions.Filenames[0], "http") {
|
||||
return cmdutil.UsageErrorf(cmd, "--raw cannot read from a url")
|
||||
}
|
||||
if o.FilenameOptions.Recursive {
|
||||
return cmdutil.UsageErrorf(cmd, "--raw and --recursive are mutually exclusive")
|
||||
}
|
||||
if len(o.Selector) > 0 {
|
||||
return cmdutil.UsageErrorf(cmd, "--raw and --selector (-l) are mutually exclusive")
|
||||
}
|
||||
if len(cmdutil.GetFlagString(cmd, "output")) > 0 {
|
||||
return cmdutil.UsageErrorf(cmd, "--raw and --output are mutually exclusive")
|
||||
}
|
||||
if _, err := url.ParseRequestURI(o.Raw); err != nil {
|
||||
return cmdutil.UsageErrorf(cmd, "--raw must be a valid URL path: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func RunCreate(f cmdutil.Factory, cmd *cobra.Command, out, errOut io.Writer, options *CreateOptions) error {
|
||||
// raw only makes sense for a single file resource multiple objects aren't likely to do what you want.
|
||||
// the validator enforces this, so
|
||||
if len(options.Raw) > 0 {
|
||||
restClient, err := f.RESTClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var data io.ReadCloser
|
||||
if options.FilenameOptions.Filenames[0] == "-" {
|
||||
data = os.Stdin
|
||||
} else {
|
||||
data, err = os.Open(options.FilenameOptions.Filenames[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// TODO post content with stream. Right now it ignores body content
|
||||
bytes, err := restClient.Post().RequestURI(options.Raw).Body(data).DoRaw()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintf(out, "%v", string(bytes))
|
||||
return nil
|
||||
}
|
||||
|
||||
if options.EditBeforeCreate {
|
||||
return RunEditOnCreate(f, out, errOut, cmd, &options.FilenameOptions)
|
||||
}
|
||||
|
@ -33,7 +33,8 @@ func TestExtraArgsFail(t *testing.T) {
|
||||
|
||||
f, _, _, _ := cmdtesting.NewAPIFactory()
|
||||
c := NewCmdCreate(f, buf, errBuf)
|
||||
if ValidateArgs(c, []string{"rc"}) == nil {
|
||||
options := CreateOptions{}
|
||||
if options.ValidateArgs(c, []string{"rc"}) == nil {
|
||||
t.Errorf("unexpected non-error")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user