2014-10-06 01:24:19 +00:00
/ *
2015-05-01 16:19:44 +00:00
Copyright 2014 The Kubernetes Authors All rights reserved .
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"
2015-07-15 12:10:47 +00:00
"io/ioutil"
2015-06-27 04:25:08 +00:00
"os"
2015-07-15 12:10:47 +00:00
"path/filepath"
2014-10-06 01:24:19 +00:00
2015-04-11 06:06:05 +00:00
"github.com/spf13/cobra"
2015-08-05 22:05:17 +00:00
"github.com/golang/glog"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/kubectl"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource"
2014-10-06 01:24:19 +00:00
)
2015-02-20 21:28:43 +00:00
const (
2015-06-27 04:25:08 +00:00
replace_long = ` Replace a resource by filename or stdin .
2015-02-20 21:28:43 +00:00
2015-08-07 22:21:31 +00:00
JSON and YAML formats are accepted . If replacing an existing resource , the
complete resource spec must be provided . This can be obtained by
$ kubectl get TYPE NAME - o yaml
2015-07-13 20:46:51 +00:00
2015-08-12 20:18:47 +00:00
Please refer to the models in https : //htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/HEAD/docs/api-reference/definitions.html to find if a field is mutable.`
2015-08-12 16:50:09 +00:00
replace_example = ` # Replace a pod using the data in pod . json .
2015-07-16 00:20:39 +00:00
$ kubectl replace - f . / pod . json
2015-02-20 21:28:43 +00:00
2015-08-12 16:50:09 +00:00
# Replace a pod based on the JSON passed into stdin .
2015-06-27 04:25:08 +00:00
$ cat pod . json | kubectl replace - f -
2015-06-17 23:56:55 +00:00
2015-08-12 16:50:09 +00:00
# Update a single - container pod ' s image version ( tag ) to v4
2015-08-07 22:21:31 +00:00
kubectl get pod mypod - o yaml | sed ' s / \ ( image : myimage \ ) : . * $ / \ 1 : v4 / ' | kubectl replace - f -
2015-08-12 16:50:09 +00:00
# Force replace , delete and then re - create the resource
2015-07-16 00:20:39 +00:00
kubectl replace -- force - f . / pod . json `
2015-02-20 21:28:43 +00:00
)
2015-06-27 04:25:08 +00:00
func NewCmdReplace ( f * cmdutil . Factory , out io . Writer ) * cobra . Command {
2014-10-06 01:24:19 +00:00
cmd := & cobra . Command {
2015-06-27 04:25:08 +00:00
Use : "replace -f FILENAME" ,
// update is deprecated.
Aliases : [ ] string { "update" } ,
Short : "Replace a resource by filename or stdin." ,
Long : replace_long ,
Example : replace_example ,
2014-10-06 01:24:19 +00:00
Run : func ( cmd * cobra . Command , args [ ] string ) {
2015-07-01 22:47:43 +00:00
cmdutil . CheckErr ( cmdutil . ValidateOutputArgs ( cmd ) )
2015-08-05 14:21:47 +00:00
err := RunReplace ( f , out , cmd , args )
2015-07-31 23:43:39 +00:00
cmdutil . CheckErr ( err )
2014-10-06 01:24:19 +00:00
} ,
}
2015-06-27 04:25:08 +00:00
usage := "Filename, directory, or URL to file to use to replace the resource."
2015-08-05 14:21:47 +00:00
kubectl . AddJsonFilenameFlag ( cmd , usage )
2015-03-17 15:49:35 +00:00
cmd . MarkFlagRequired ( "filename" )
2015-06-25 00:33:46 +00:00
cmd . Flags ( ) . Bool ( "force" , false , "Delete and re-create the specified resource" )
2015-08-10 16:03:43 +00:00
cmd . Flags ( ) . Bool ( "cascade" , false , "Only relevant during a force replace. If true, cascade the deletion of the resources managed by this resource (e.g. Pods created by a ReplicationController)." )
2015-06-27 04:25:08 +00:00
cmd . Flags ( ) . Int ( "grace-period" , - 1 , "Only relevant during a force replace. Period of time in seconds given to the old resource to terminate gracefully. Ignored if negative." )
cmd . Flags ( ) . Duration ( "timeout" , 0 , "Only relevant during a force replace. The length of time to wait before giving up on a delete of the old resource, zero means determine a timeout from the size of the object" )
2015-08-18 01:15:34 +00:00
cmdutil . AddValidateFlag ( cmd )
2015-07-01 22:47:43 +00:00
cmdutil . AddOutputFlagsForMutation ( cmd )
2014-10-06 01:24:19 +00:00
return cmd
}
2015-01-15 21:55:53 +00:00
2015-08-05 14:21:47 +00:00
func RunReplace ( f * cmdutil . Factory , out io . Writer , cmd * cobra . Command , args [ ] string ) error {
2015-07-09 23:15:42 +00:00
if len ( os . Args ) > 1 && os . Args [ 1 ] == "update" {
2015-06-27 04:25:08 +00:00
printDeprecationWarning ( "replace" , "update" )
}
2015-08-18 01:15:34 +00:00
schema , err := f . Validator ( cmdutil . GetFlagBool ( cmd , "validate" ) )
2015-03-09 22:08:16 +00:00
if err != nil {
return err
}
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
}
2015-06-25 00:33:46 +00:00
force := cmdutil . GetFlagBool ( cmd , "force" )
2015-08-05 14:21:47 +00:00
filenames := cmdutil . GetFlagStringSlice ( cmd , "filename" )
2015-05-29 00:25:44 +00:00
if len ( filenames ) == 0 {
2015-06-27 04:25:08 +00:00
return cmdutil . UsageError ( cmd , "Must specify --filename to replace" )
2015-03-09 22:08:16 +00:00
}
2015-08-05 14:21:47 +00:00
shortOutput := cmdutil . GetFlagString ( cmd , "output" ) == "name"
2015-06-25 00:33:46 +00:00
if force {
2015-07-01 22:47:43 +00:00
return forceReplace ( f , out , cmd , args , filenames , shortOutput )
2015-06-25 00:33:46 +00:00
}
2015-03-14 10:45:18 +00:00
mapper , typer := f . Object ( )
2015-03-27 13:46:17 +00:00
r := resource . NewBuilder ( mapper , typer , f . ClientMapperForCommand ( ) ) .
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 ( ) .
FilenameParam ( enforceNamespace , filenames ... ) .
2015-03-09 22:08:16 +00:00
Flatten ( ) .
Do ( )
err = r . Err ( )
if err != nil {
return err
}
2015-06-15 02:48:56 +00:00
return r . Visit ( func ( info * resource . Info , err error ) error {
if err != nil {
return err
}
2015-03-09 22:08:16 +00:00
data , err := info . Mapping . Codec . Encode ( info . Object )
if err != nil {
2015-06-27 04:25:08 +00:00
return cmdutil . AddSourceToErr ( "replacing" , info . Source , err )
2015-03-09 22:08:16 +00:00
}
2015-06-27 04:25:08 +00:00
obj , err := resource . NewHelper ( info . Client , info . Mapping ) . Replace ( info . Namespace , info . Name , true , data )
2015-03-09 22:08:16 +00:00
if err != nil {
2015-06-27 04:25:08 +00:00
return cmdutil . AddSourceToErr ( "replacing" , info . Source , err )
2015-03-09 22:08:16 +00:00
}
info . Refresh ( obj , true )
2015-06-05 03:52:46 +00:00
printObjectSpecificMessage ( obj , out )
2015-07-01 22:47:43 +00:00
cmdutil . PrintSuccess ( mapper , shortOutput , out , info . Mapping . Resource , info . Name , "replaced" )
2015-03-09 22:08:16 +00:00
return nil
} )
}
2015-08-05 14:21:47 +00:00
func forceReplace ( f * cmdutil . Factory , out io . Writer , cmd * cobra . Command , args [ ] string , filenames [ ] string , shortOutput bool ) error {
2015-08-18 01:15:34 +00:00
schema , err := f . Validator ( cmdutil . GetFlagBool ( cmd , "validate" ) )
2015-06-25 00:33:46 +00:00
if err != nil {
return err
}
2015-06-26 20:49:34 +00:00
cmdNamespace , enforceNamespace , err := f . DefaultNamespace ( )
2015-06-25 00:33:46 +00:00
if err != nil {
return err
}
2015-07-15 12:10:47 +00:00
for i , filename := range filenames {
if filename == "-" {
tempDir , err := ioutil . TempDir ( "" , "kubectl_replace_" )
if err != nil {
return err
}
defer os . RemoveAll ( tempDir )
tempFilename := filepath . Join ( tempDir , "resource.stdin" )
err = cmdutil . DumpReaderToFile ( os . Stdin , tempFilename )
if err != nil {
return err
}
filenames [ i ] = tempFilename
}
}
2015-06-25 00:33:46 +00:00
mapper , typer := f . Object ( )
r := resource . NewBuilder ( mapper , typer , f . ClientMapperForCommand ( ) ) .
ContinueOnError ( ) .
NamespaceParam ( cmdNamespace ) . DefaultNamespace ( ) .
2015-06-26 20:49:34 +00:00
FilenameParam ( enforceNamespace , filenames ... ) .
2015-06-25 00:33:46 +00:00
ResourceTypeOrNameArgs ( false , args ... ) . RequireObject ( false ) .
Flatten ( ) .
Do ( )
err = r . Err ( )
if err != nil {
return err
}
2015-06-27 04:25:08 +00:00
//Replace will create a resource if it doesn't exist already, so ignore not found error
2015-06-25 00:33:46 +00:00
ignoreNotFound := true
// By default use a reaper to delete all related resources.
if cmdutil . GetFlagBool ( cmd , "cascade" ) {
glog . Warningf ( "\"cascade\" is set, kubectl will delete and re-create all resources managed by this resource (e.g. Pods created by a ReplicationController). Consider using \"kubectl rolling-update\" if you want to update a ReplicationController together with its Pods." )
2015-07-01 22:47:43 +00:00
err = ReapResult ( r , f , out , cmdutil . GetFlagBool ( cmd , "cascade" ) , ignoreNotFound , cmdutil . GetFlagDuration ( cmd , "timeout" ) , cmdutil . GetFlagInt ( cmd , "grace-period" ) , shortOutput , mapper )
2015-06-25 00:33:46 +00:00
} else {
2015-07-01 22:47:43 +00:00
err = DeleteResult ( r , out , ignoreNotFound , shortOutput , mapper )
2015-06-25 00:33:46 +00:00
}
if err != nil {
return err
}
r = resource . NewBuilder ( mapper , typer , f . ClientMapperForCommand ( ) ) .
Schema ( schema ) .
ContinueOnError ( ) .
2015-06-26 20:49:34 +00:00
NamespaceParam ( cmdNamespace ) . DefaultNamespace ( ) .
FilenameParam ( enforceNamespace , filenames ... ) .
2015-06-25 00:33:46 +00:00
Flatten ( ) .
Do ( )
err = r . Err ( )
if err != nil {
return err
}
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-06-25 00:33:46 +00:00
data , err := info . Mapping . Codec . Encode ( info . Object )
if err != nil {
return err
}
obj , err := resource . NewHelper ( info . Client , info . Mapping ) . Create ( info . Namespace , true , data )
if err != nil {
return err
}
count ++
info . Refresh ( obj , true )
printObjectSpecificMessage ( obj , out )
2015-07-01 22:47:43 +00:00
cmdutil . PrintSuccess ( mapper , shortOutput , out , info . Mapping . Resource , info . Name , "replaced" )
2015-06-25 00:33:46 +00:00
return nil
} )
if err != nil {
return err
}
if count == 0 {
2015-06-27 04:25:08 +00:00
return fmt . Errorf ( "no objects passed to replace" )
2015-06-25 00:33:46 +00:00
}
return nil
}