2014-10-06 01:24:19 +00:00
/ *
2016-06-03 00:25:58 +00:00
Copyright 2014 The Kubernetes Authors .
2014-10-06 01:24:19 +00:00
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 cmd
import (
2014-10-27 02:21:31 +00:00
"fmt"
2014-10-06 01:24:19 +00:00
"io"
2017-10-19 15:00:50 +00:00
"os"
2017-05-30 17:15:39 +00:00
"runtime"
2017-10-19 15:00:50 +00:00
"strings"
2014-10-06 01:24:19 +00:00
"github.com/spf13/cobra"
2014-12-31 23:35:52 +00:00
2017-10-19 15:00:50 +00:00
"net/url"
2017-10-09 19:44:02 +00:00
"k8s.io/apimachinery/pkg/api/meta"
2017-01-11 14:09:48 +00:00
"k8s.io/apimachinery/pkg/runtime/schema"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/kubectl"
2016-10-07 22:24:42 +00:00
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
2015-08-05 22:03:47 +00:00
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
2017-04-18 12:44:25 +00:00
"k8s.io/kubernetes/pkg/kubectl/cmd/util/editor"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/kubectl/resource"
2017-07-07 04:04:11 +00:00
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
2014-10-06 01:24:19 +00:00
)
2017-01-18 03:07:55 +00:00
type CreateOptions struct {
FilenameOptions resource . FilenameOptions
Selector string
EditBeforeCreate bool
2017-10-19 15:00:50 +00:00
Raw string
2017-01-18 03:07:55 +00:00
}
2016-05-20 17:49:56 +00:00
var (
2017-05-25 20:37:56 +00:00
createLong = templates . LongDesc ( i18n . T ( `
2017-05-25 19:23:22 +00:00
Create a resource from a file or from stdin .
2015-02-20 21:28:43 +00:00
2017-03-15 03:49:10 +00:00
JSON and YAML formats are accepted . ` ) )
2016-10-07 22:24:42 +00:00
2017-05-25 20:37:56 +00:00
createExample = templates . Examples ( i18n . T ( `
2016-05-20 17:49:56 +00:00
# Create a pod using the data in pod . json .
kubectl create - f . / pod . json
2015-02-20 21:28:43 +00:00
2016-05-20 17:49:56 +00:00
# Create a pod based on the JSON passed into stdin .
2016-09-21 23:41:07 +00:00
cat pod . json | kubectl create - f -
# Edit the data in docker - registry . yaml in JSON using the v1 API format then create the resource using the edited data .
2017-03-15 03:49:10 +00:00
kubectl create - f docker - registry . yaml -- edit -- output - version = v1 - o json ` ) )
2015-02-20 21:28:43 +00:00
)
2016-09-21 23:41:07 +00:00
func NewCmdCreate ( f cmdutil . Factory , out , errOut io . Writer ) * cobra . Command {
2017-01-18 03:07:55 +00:00
var options CreateOptions
2015-08-14 18:46:43 +00:00
2014-10-06 01:24:19 +00:00
cmd := & cobra . Command {
2015-03-11 17:22:08 +00:00
Use : "create -f FILENAME" ,
2017-05-25 19:23:22 +00:00
Short : i18n . T ( "Create a resource from a file or from stdin." ) ,
2017-05-25 20:37:56 +00:00
Long : createLong ,
Example : createExample ,
2014-10-06 01:24:19 +00:00
Run : func ( cmd * cobra . Command , args [ ] string ) {
2017-06-14 21:14:42 +00:00
if cmdutil . IsFilenameSliceEmpty ( options . FilenameOptions . Filenames ) {
2016-10-20 14:41:46 +00:00
defaultRunFunc := cmdutil . DefaultSubCommandRun ( errOut )
defaultRunFunc ( cmd , args )
2015-10-21 14:41:42 +00:00
return
}
2017-10-19 15:00:50 +00:00
cmdutil . CheckErr ( options . ValidateArgs ( cmd , args ) )
2017-01-18 03:07:55 +00:00
cmdutil . CheckErr ( RunCreate ( f , cmd , out , errOut , & options ) )
2015-03-09 22:08:16 +00:00
} ,
}
2015-03-29 03:38:46 +00:00
2016-08-17 18:28:07 +00:00
usage := "to use to create the resource"
2017-01-18 03:07:55 +00:00
cmdutil . AddFilenameOptionFlags ( cmd , & options . FilenameOptions , usage )
2015-03-17 15:49:35 +00:00
cmd . MarkFlagRequired ( "filename" )
2015-09-10 21:58:09 +00:00
cmdutil . AddValidateFlags ( cmd )
2016-10-11 15:41:02 +00:00
cmdutil . AddPrinterFlags ( cmd )
2017-01-18 03:07:55 +00:00
cmd . Flags ( ) . BoolVar ( & options . EditBeforeCreate , "edit" , false , "Edit the API resource before creating" )
2017-05-30 17:15:39 +00:00
cmd . Flags ( ) . Bool ( "windows-line-endings" , runtime . GOOS == "windows" ,
"Only relevant if --edit=true. Defaults to the line ending native to your platform." )
2015-11-04 21:47:08 +00:00
cmdutil . AddApplyAnnotationFlags ( cmd )
2016-01-22 18:33:23 +00:00
cmdutil . AddRecordFlag ( cmd )
2016-10-11 15:41:02 +00:00
cmdutil . AddDryRunFlag ( cmd )
2016-03-10 01:27:19 +00:00
cmdutil . AddInclude3rdPartyFlags ( cmd )
2017-08-17 12:27:11 +00:00
cmd . Flags ( ) . StringVarP ( & options . Selector , "selector" , "l" , "" , "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)" )
2017-10-19 15:00:50 +00:00
cmd . Flags ( ) . StringVar ( & options . Raw , "raw" , options . Raw , "Raw URI to POST to the server. Uses the transport specified by the kubeconfig file." )
2015-10-21 14:41:42 +00:00
// create subcommands
cmd . AddCommand ( NewCmdCreateNamespace ( f , out ) )
2016-01-13 23:49:11 +00:00
cmd . AddCommand ( NewCmdCreateQuota ( f , out ) )
2016-10-20 14:41:46 +00:00
cmd . AddCommand ( NewCmdCreateSecret ( f , out , errOut ) )
2016-02-19 02:24:21 +00:00
cmd . AddCommand ( NewCmdCreateConfigMap ( f , out ) )
2016-02-17 18:15:32 +00:00
cmd . AddCommand ( NewCmdCreateServiceAccount ( f , out ) )
2016-10-20 14:41:46 +00:00
cmd . AddCommand ( NewCmdCreateService ( f , out , errOut ) )
2017-03-08 10:11:29 +00:00
cmd . AddCommand ( NewCmdCreateDeployment ( f , out , errOut ) )
2017-02-15 07:38:13 +00:00
cmd . AddCommand ( NewCmdCreateClusterRole ( f , out ) )
2016-11-18 16:23:59 +00:00
cmd . AddCommand ( NewCmdCreateClusterRoleBinding ( f , out ) )
2017-01-10 05:59:49 +00:00
cmd . AddCommand ( NewCmdCreateRole ( f , out ) )
2016-12-19 19:27:53 +00:00
cmd . AddCommand ( NewCmdCreateRoleBinding ( f , out ) )
2016-11-18 12:47:39 +00:00
cmd . AddCommand ( NewCmdCreatePodDisruptionBudget ( f , out ) )
2017-10-31 09:16:25 +00:00
cmd . AddCommand ( NewCmdCreatePriorityClass ( f , out ) )
2015-03-09 22:08:16 +00:00
return cmd
}
2014-10-06 01:24:19 +00:00
2017-10-19 15:00:50 +00:00
func ( o * CreateOptions ) ValidateArgs ( cmd * cobra . Command , args [ ] string ) error {
2015-03-24 18:21:52 +00:00
if len ( args ) != 0 {
2017-06-14 21:14:42 +00:00
return cmdutil . UsageErrorf ( cmd , "Unexpected args: %v" , args )
2015-03-24 18:21:52 +00:00
}
2017-10-19 15:00:50 +00:00
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 )
}
}
2015-03-24 18:21:52 +00:00
return nil
}
2017-01-18 03:07:55 +00:00
func RunCreate ( f cmdutil . Factory , cmd * cobra . Command , out , errOut io . Writer , options * CreateOptions ) error {
2017-10-19 15:00:50 +00:00
// 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
}
2017-01-18 03:07:55 +00:00
if options . EditBeforeCreate {
return RunEditOnCreate ( f , out , errOut , cmd , & options . FilenameOptions )
2016-09-21 23:41:07 +00:00
}
2017-09-28 22:39:17 +00:00
schema , err := f . Validator ( cmdutil . GetFlagBool ( cmd , "validate" ) )
2015-03-09 22:08:16 +00:00
if err != nil {
return err
}
2015-01-02 18:08:37 +00:00
2015-06-26 20:49:34 +00:00
cmdNamespace , enforceNamespace , err := f . DefaultNamespace ( )
2015-03-09 22:08:16 +00:00
if err != nil {
return err
}
2014-11-04 18:59:23 +00:00
2017-11-14 03:43:58 +00:00
r := f . NewBuilder ( ) .
2017-11-14 04:01:51 +00:00
Unstructured ( ) .
2015-05-07 20:53:43 +00:00
Schema ( schema ) .
2015-03-09 22:08:16 +00:00
ContinueOnError ( ) .
2015-06-26 20:49:34 +00:00
NamespaceParam ( cmdNamespace ) . DefaultNamespace ( ) .
2017-01-18 03:07:55 +00:00
FilenameParam ( enforceNamespace , & options . FilenameOptions ) .
2017-08-04 06:54:17 +00:00
LabelSelectorParam ( options . Selector ) .
2015-03-09 22:08:16 +00:00
Flatten ( ) .
Do ( )
err = r . Err ( )
if err != nil {
return err
2014-10-06 01:24:19 +00:00
}
2015-03-09 22:08:16 +00:00
2016-10-11 15:41:02 +00:00
dryRun := cmdutil . GetFlagBool ( cmd , "dry-run" )
2016-12-08 20:26:37 +00:00
output := cmdutil . GetFlagString ( cmd , "output" )
2017-11-14 04:01:51 +00:00
mapper := r . Mapper ( ) . RESTMapper
2016-10-11 15:41:02 +00:00
2015-03-09 22:08:16 +00:00
count := 0
2015-06-15 02:48:56 +00:00
err = r . Visit ( func ( info * resource . Info , err error ) error {
if err != nil {
return err
}
2015-12-21 05:37:49 +00:00
if err := kubectl . CreateOrUpdateAnnotation ( cmdutil . GetFlagBool ( cmd , cmdutil . ApplyAnnotationsFlag ) , info , f . JSONEncoder ( ) ) ; err != nil {
2015-09-10 21:32:57 +00:00
return cmdutil . AddSourceToErr ( "creating" , info . Source , err )
}
2016-01-22 18:33:23 +00:00
if cmdutil . ShouldRecord ( cmd , info ) {
2017-02-25 15:40:50 +00:00
if err := cmdutil . RecordChangeCause ( info . Object , f . Command ( cmd , false ) ) ; err != nil {
2016-01-22 18:33:23 +00:00
return cmdutil . AddSourceToErr ( "creating" , info . Source , err )
}
}
2016-10-11 15:41:02 +00:00
if ! dryRun {
if err := createAndRefresh ( info ) ; err != nil {
return cmdutil . AddSourceToErr ( "creating" , info . Source , err )
}
2015-03-09 22:08:16 +00:00
}
2015-09-10 21:32:57 +00:00
2015-03-09 22:08:16 +00:00
count ++
2016-12-08 20:26:37 +00:00
shortOutput := output == "name"
if len ( output ) > 0 && ! shortOutput {
2017-10-31 18:45:35 +00:00
return f . PrintResourceInfoForCommand ( cmd , info , out )
2016-12-08 20:26:37 +00:00
}
2015-07-01 22:47:43 +00:00
if ! shortOutput {
2016-05-24 12:56:12 +00:00
f . PrintObjectSpecificMessage ( info . Object , out )
2015-07-01 22:47:43 +00:00
}
2016-10-11 15:41:02 +00:00
2017-10-31 15:58:38 +00:00
f . PrintSuccess ( mapper , shortOutput , out , info . Mapping . Resource , info . Name , dryRun , "created" )
2015-03-09 22:08:16 +00:00
return nil
} )
if err != nil {
return err
}
if count == 0 {
return fmt . Errorf ( "no objects passed to create" )
}
return nil
2014-10-06 01:24:19 +00:00
}
2015-06-05 03:52:46 +00:00
2016-09-21 23:41:07 +00:00
func RunEditOnCreate ( f cmdutil . Factory , out , errOut io . Writer , cmd * cobra . Command , options * resource . FilenameOptions ) error {
2017-04-18 12:44:25 +00:00
editOptions := & editor . EditOptions {
EditMode : editor . EditBeforeCreateMode ,
FilenameOptions : * options ,
ValidateOptions : cmdutil . ValidateOptions {
EnableValidation : cmdutil . GetFlagBool ( cmd , "validate" ) ,
} ,
Output : cmdutil . GetFlagString ( cmd , "output" ) ,
WindowsLineEndings : cmdutil . GetFlagBool ( cmd , "windows-line-endings" ) ,
ApplyAnnotation : cmdutil . GetFlagBool ( cmd , cmdutil . ApplyAnnotationsFlag ) ,
Record : cmdutil . GetFlagBool ( cmd , "record" ) ,
ChangeCause : f . Command ( cmd , false ) ,
Include3rdParty : cmdutil . GetFlagBool ( cmd , "include-extended-apis" ) ,
}
2017-08-11 06:21:44 +00:00
err := editOptions . Complete ( f , out , errOut , [ ] string { } , cmd )
2017-04-18 12:44:25 +00:00
if err != nil {
return err
}
return editOptions . Run ( )
2016-09-21 23:41:07 +00:00
}
2015-11-05 02:29:56 +00:00
// createAndRefresh creates an object from input info and refreshes info with that object
func createAndRefresh ( info * resource . Info ) error {
obj , err := resource . NewHelper ( info . Client , info . Mapping ) . Create ( info . Namespace , true , info . Object )
if err != nil {
return err
}
info . Refresh ( obj , true )
return nil
}
2015-10-21 14:41:42 +00:00
// NameFromCommandArgs is a utility function for commands that assume the first argument is a resource name
func NameFromCommandArgs ( cmd * cobra . Command , args [ ] string ) ( string , error ) {
if len ( args ) == 0 {
2017-06-14 21:14:42 +00:00
return "" , cmdutil . UsageErrorf ( cmd , "NAME is required" )
2015-10-21 14:41:42 +00:00
}
return args [ 0 ] , nil
}
// CreateSubcommandOptions is an options struct to support create subcommands
type CreateSubcommandOptions struct {
// Name of resource being created
Name string
// StructuredGenerator is the resource generator for the object being created
StructuredGenerator kubectl . StructuredGenerator
// DryRun is true if the command should be simulated but not run against the server
2017-06-14 21:14:42 +00:00
DryRun bool
2015-10-21 14:41:42 +00:00
OutputFormat string
}
// RunCreateSubcommand executes a create subcommand using the specified options
2016-10-13 00:18:39 +00:00
func RunCreateSubcommand ( f cmdutil . Factory , cmd * cobra . Command , out io . Writer , options * CreateSubcommandOptions ) error {
2017-10-09 19:44:02 +00:00
namespace , nsOverriden , err := f . DefaultNamespace ( )
2015-10-21 14:41:42 +00:00
if err != nil {
return err
}
obj , err := options . StructuredGenerator . StructuredGenerate ( )
if err != nil {
return err
}
2016-09-16 19:50:34 +00:00
mapper , typer := f . Object ( )
2016-05-21 04:15:31 +00:00
gvks , _ , err := typer . ObjectKinds ( obj )
if err != nil {
return err
}
gvk := gvks [ 0 ]
2016-11-21 02:55:31 +00:00
mapping , err := mapper . RESTMapping ( schema . GroupKind { Group : gvk . Group , Kind : gvk . Kind } , gvk . Version )
2015-10-21 14:41:42 +00:00
if err != nil {
return err
}
2015-12-21 05:37:49 +00:00
client , err := f . ClientForMapping ( mapping )
2015-10-21 14:41:42 +00:00
if err != nil {
return err
}
2015-12-21 05:37:49 +00:00
resourceMapper := & resource . Mapper {
ObjectTyper : typer ,
RESTMapper : mapper ,
ClientMapper : resource . ClientMapperFunc ( f . ClientForMapping ) ,
}
2016-03-11 04:49:00 +00:00
info , err := resourceMapper . InfoForObject ( obj , nil )
2015-10-21 14:41:42 +00:00
if err != nil {
return err
}
2017-01-23 07:15:37 +00:00
if err := kubectl . CreateOrUpdateAnnotation ( cmdutil . GetFlagBool ( cmd , cmdutil . ApplyAnnotationsFlag ) , info , f . JSONEncoder ( ) ) ; err != nil {
2015-10-21 14:41:42 +00:00
return err
}
2017-01-23 07:15:37 +00:00
obj = info . Object
2015-10-21 14:41:42 +00:00
if ! options . DryRun {
obj , err = resource . NewHelper ( client , mapping ) . Create ( namespace , false , info . Object )
if err != nil {
return err
}
2017-10-09 19:44:02 +00:00
} else {
if meta , err := meta . Accessor ( obj ) ; err == nil && nsOverriden {
meta . SetNamespace ( namespace )
}
2015-10-21 14:41:42 +00:00
}
if useShortOutput := options . OutputFormat == "name" ; useShortOutput || len ( options . OutputFormat ) == 0 {
2017-10-31 15:58:38 +00:00
f . PrintSuccess ( mapper , useShortOutput , out , mapping . Resource , info . Name , options . DryRun , "created" )
2015-10-21 14:41:42 +00:00
return nil
}
2017-05-16 21:52:51 +00:00
return f . PrintObject ( cmd , false , mapper , obj , out )
2015-10-21 14:41:42 +00:00
}