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:
Kubernetes Submit Queue 2017-08-06 14:37:11 -07:00 committed by GitHub
commit ca1ebbfc25
2 changed files with 44 additions and 15 deletions

View File

@ -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)
}
}
}

View File

@ -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