mirror of https://github.com/kubernetes/kops.git
Merge pull request #3089 from gambol99/replace_cmd
Automatic merge from submit-queue Kops Replace Command - create unprovisioned The current 'kops replace' fails if the resource does not exist, which is annoying if you want to use the feature to drive your CI. This PR adds a --create option to create any resource which does not exist. At the moment we limit this to instanceGroups only. I'd also like to see this command perhaps be renamed to kops apply? - added a --create command line option to the replace command to create unprovisioned resources
This commit is contained in:
commit
ca1ebbfc25
|
|
@ -26,6 +26,7 @@ import (
|
|||
"k8s.io/kops/cmd/kops/util"
|
||||
"k8s.io/kops/util/pkg/vfs"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
kopsapi "k8s.io/kops/pkg/apis/kops"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
|
|
@ -34,29 +35,37 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
replace_long = templates.LongDesc(i18n.T(`
|
||||
replaceLong = templates.LongDesc(i18n.T(`
|
||||
Replace a resource specification by filename or stdin.`))
|
||||
|
||||
replace_example = templates.Examples(i18n.T(`
|
||||
replaceExample = templates.Examples(i18n.T(`
|
||||
# Replace a cluster specification using a file
|
||||
kops replace -f my-cluster.yaml
|
||||
|
||||
# Note, if the resource does not exist the command will error, use --force to provision resource
|
||||
kops replace -f my-cluster.yaml --force
|
||||
`))
|
||||
|
||||
replace_short = i18n.T(`Replace cluster resources.`)
|
||||
replaceShort = i18n.T(`Replace cluster resources.`)
|
||||
)
|
||||
|
||||
type ReplaceOptions struct {
|
||||
// replaceOptions is the options for the command
|
||||
type replaceOptions struct {
|
||||
// a list of files containing resources
|
||||
resource.FilenameOptions
|
||||
// create any resources not found - we limit to instance groups only for now
|
||||
force bool
|
||||
}
|
||||
|
||||
// NewCmdReplace returns a new replace command
|
||||
func NewCmdReplace(f *util.Factory, out io.Writer) *cobra.Command {
|
||||
options := &ReplaceOptions{}
|
||||
options := &replaceOptions{}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "replace -f FILENAME",
|
||||
Short: replace_short,
|
||||
Long: replace_long,
|
||||
Example: replace_example,
|
||||
Short: replaceShort,
|
||||
Long: replaceLong,
|
||||
Example: replaceExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if cmdutil.IsFilenameEmpty(options.Filenames) {
|
||||
cmd.Help()
|
||||
|
|
@ -66,14 +75,15 @@ func NewCmdReplace(f *util.Factory, out io.Writer) *cobra.Command {
|
|||
cmdutil.CheckErr(RunReplace(f, cmd, out, options))
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringSliceVarP(&options.Filenames, "filename", "f", options.Filenames, "A list of one or more files separated by a comma.")
|
||||
cmd.Flags().BoolVarP(&options.force, "force", "", false, "Force any changes, which will also create any non-existing respurce (defaults to instancegroups only)")
|
||||
cmd.MarkFlagRequired("filename")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func RunReplace(f *util.Factory, cmd *cobra.Command, out io.Writer, c *ReplaceOptions) error {
|
||||
// RunReplace processes the replace command
|
||||
func RunReplace(f *util.Factory, cmd *cobra.Command, out io.Writer, c *replaceOptions) error {
|
||||
clientset, err := f.Clientset()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -92,7 +102,6 @@ func RunReplace(f *util.Factory, cmd *cobra.Command, out io.Writer, c *ReplaceOp
|
|||
sections := bytes.Split(contents, []byte("\n---\n"))
|
||||
|
||||
for _, section := range sections {
|
||||
|
||||
o, gvk, err := codec.Decode(section, nil, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing file %q: %v", f, err)
|
||||
|
|
@ -123,16 +132,32 @@ func RunReplace(f *util.Factory, cmd *cobra.Command, out io.Writer, c *ReplaceOp
|
|||
if cluster == nil {
|
||||
return fmt.Errorf("cluster %q not found", clusterName)
|
||||
}
|
||||
_, err = clientset.InstanceGroupsFor(cluster).Update(v)
|
||||
// check if the instancegroup exists already
|
||||
igName := v.ObjectMeta.Name
|
||||
ig, err := clientset.InstanceGroupsFor(cluster).Get(igName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error replacing instanceGroup: %v", err)
|
||||
return fmt.Errorf("unable to check for instanceGroup: %v", err)
|
||||
}
|
||||
switch ig {
|
||||
case nil:
|
||||
if !c.force {
|
||||
return fmt.Errorf("instanceGroup: %v does not exist (try adding --force flag)", igName)
|
||||
}
|
||||
glog.Infof("instanceGroup: %v was not found, creating resource now", igName)
|
||||
_, err = clientset.InstanceGroupsFor(cluster).Create(v)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating instanceGroup: %v", err)
|
||||
}
|
||||
default:
|
||||
_, err = clientset.InstanceGroupsFor(cluster).Update(v)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error replacing instanceGroup: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
glog.V(2).Infof("Type of object was %T", v)
|
||||
return fmt.Errorf("Unhandled kind %q in %q", gvk, f)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,12 +19,16 @@ kops replace -f FILENAME
|
|||
```
|
||||
# Replace a cluster specification using a file
|
||||
kops replace -f my-cluster.yaml
|
||||
|
||||
# Note, if the resource does not exist the command will error, use --force to provision resource
|
||||
kops replace -f my-cluster.yaml --force
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-f, --filename stringSlice A list of one or more files separated by a comma.
|
||||
--force Force any changes, which will also create any non-existing respurce (defaults to instancegroups only)
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
|
|
|||
Loading…
Reference in New Issue