Merge pull request #11987 from johngmyers/edit-set

Change set and unset commands into flags on "kops edit cluster"
This commit is contained in:
Kubernetes Prow Robot 2021-07-14 14:04:40 -07:00 committed by GitHub
commit e08fdb0c4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 210 additions and 1110 deletions

6
cmd/kops/BUILD.bazel generated
View File

@ -42,18 +42,12 @@ go_library(
"rollingupdate.go",
"rollingupdate_cluster.go",
"root.go",
"set.go",
"set_cluster.go",
"set_instancegroups.go",
"toolbox.go",
"toolbox_dump.go",
"toolbox_instance_selector.go",
"toolbox_template.go",
"trust.go",
"trust_keypair.go",
"unset.go",
"unset_cluster.go",
"unset_instancegroups.go",
"update.go",
"update_cluster.go",
"upgrade.go",

View File

@ -31,9 +31,11 @@ import (
api "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/validation"
"k8s.io/kops/pkg/assets"
"k8s.io/kops/pkg/client/simple"
"k8s.io/kops/pkg/commands"
"k8s.io/kops/pkg/commands/commandutils"
"k8s.io/kops/pkg/edit"
"k8s.io/kops/pkg/featureflag"
"k8s.io/kops/pkg/kopscodecs"
"k8s.io/kops/pkg/pretty"
"k8s.io/kops/pkg/try"
@ -45,17 +47,22 @@ import (
type EditClusterOptions struct {
ClusterName string
// Sets allows setting values directly in the spec.
Sets []string
// Unsets allows unsetting values directly in the spec.
Unsets []string
}
var (
editClusterLong = templates.LongDesc(i18n.T(`Edit a cluster configuration.
editClusterLong = pretty.LongDesc(i18n.T(`Edit a cluster configuration.
This command changes the desired cluster configuration in the registry.
To set your preferred editor, you can define the EDITOR environment variable.
When you have done this, kOps will use the editor that you have set.
kops edit does not update the cloud resources, to apply the changes use ` + pretty.Bash("kops update cluster") + `.`))
kops edit does not update the cloud resources; to apply the changes use ` + pretty.Bash("kops update cluster") + `.`))
editClusterExample = templates.Examples(i18n.T(`
# Edit a cluster configuration in AWS.
@ -78,6 +85,17 @@ func NewCmdEditCluster(f *util.Factory, out io.Writer) *cobra.Command {
},
}
if featureflag.SpecOverrideFlag.Enabled() {
cmd.Flags().StringSliceVar(&options.Sets, "set", options.Sets, "Directly set values in the spec")
cmd.RegisterFlagCompletionFunc("set", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return nil, cobra.ShellCompDirectiveNoFileComp
})
cmd.Flags().StringSliceVar(&options.Unsets, "unset", options.Unsets, "Directly unset values in the spec")
cmd.RegisterFlagCompletionFunc("unset", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return nil, cobra.ShellCompDirectiveNoFileComp
})
}
return cmd
}
@ -102,6 +120,25 @@ func RunEditCluster(ctx context.Context, f *util.Factory, out io.Writer, options
return err
}
if len(options.Unsets)+len(options.Sets) > 0 {
newCluster := oldCluster.DeepCopy()
if err := commands.UnsetClusterFields(options.Unsets, newCluster); err != nil {
return err
}
if err := commands.SetClusterFields(options.Sets, newCluster); err != nil {
return err
}
failure, err := updateCluster(ctx, clientset, oldCluster, newCluster, instanceGroups)
if err != nil {
return err
}
if failure != "" {
return fmt.Errorf("%s", failure)
}
return nil
}
var (
editor = util_editor.NewDefaultEditor(commandutils.EditorEnvs)
)
@ -200,53 +237,56 @@ func RunEditCluster(ctx context.Context, f *util.Factory, out io.Writer, options
continue
}
cloud, err := cloudup.BuildCloud(newCluster)
if err != nil {
return err
}
err = cloudup.PerformAssignments(newCluster, cloud)
if err != nil {
return preservedFile(fmt.Errorf("error populating configuration: %v", err), file, out)
}
assetBuilder := assets.NewAssetBuilder(newCluster, false)
fullCluster, err := cloudup.PopulateClusterSpec(clientset, newCluster, cloud, assetBuilder)
if err != nil {
results = editResults{
file: file,
}
results.header.addError(fmt.Sprintf("error populating cluster spec: %s", err))
containsError = true
continue
}
err = validation.DeepValidate(fullCluster, instanceGroups, true, cloud)
if err != nil {
results = editResults{
file: file,
}
results.header.addError(fmt.Sprintf("validation failed: %s", err))
containsError = true
continue
}
// Retrieve the current status of the cluster. This will eventually be part of the cluster object.
status, err := cloud.FindClusterStatus(oldCluster)
if err != nil {
return err
}
// Note we perform as much validation as we can, before writing a bad config
_, err = clientset.UpdateCluster(ctx, newCluster, status)
failure, err := updateCluster(ctx, clientset, oldCluster, newCluster, instanceGroups)
if err != nil {
return preservedFile(err, file, out)
}
if failure != "" {
results = editResults{
file: file,
}
results.header.addError(failure)
containsError = true
continue
}
return nil
}
}
func updateCluster(ctx context.Context, clientset simple.Clientset, oldCluster, newCluster *api.Cluster, instanceGroups []*api.InstanceGroup) (string, error) {
cloud, err := cloudup.BuildCloud(newCluster)
if err != nil {
return "", err
}
err = cloudup.PerformAssignments(newCluster, cloud)
if err != nil {
return "", fmt.Errorf("error populating configuration: %v", err)
}
assetBuilder := assets.NewAssetBuilder(newCluster, false)
fullCluster, err := cloudup.PopulateClusterSpec(clientset, newCluster, cloud, assetBuilder)
if err != nil {
return fmt.Sprintf("error populating cluster spec: %s", err), nil
}
err = validation.DeepValidate(fullCluster, instanceGroups, true, cloud)
if err != nil {
return fmt.Sprintf("validation failed: %s", err), nil
}
// Retrieve the current status of the cluster. This will eventually be part of the cluster object.
status, err := cloud.FindClusterStatus(oldCluster)
if err != nil {
return "", err
}
// Note we perform as much validation as we can, before writing a bad config
_, err = clientset.UpdateCluster(ctx, newCluster, status)
return "", err
}
type editResults struct {
header editHeader
file string

View File

@ -32,9 +32,13 @@ import (
api "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/validation"
"k8s.io/kops/pkg/assets"
"k8s.io/kops/pkg/client/simple"
"k8s.io/kops/pkg/commands"
"k8s.io/kops/pkg/commands/commandutils"
"k8s.io/kops/pkg/edit"
"k8s.io/kops/pkg/featureflag"
"k8s.io/kops/pkg/kopscodecs"
"k8s.io/kops/pkg/pretty"
"k8s.io/kops/pkg/try"
"k8s.io/kops/upup/pkg/fi/cloudup"
"k8s.io/kubectl/pkg/cmd/util/editor"
@ -43,14 +47,14 @@ import (
)
var (
editInstancegroupLong = templates.LongDesc(i18n.T(`Edit a cluster configuration.
editInstancegroupLong = pretty.LongDesc(i18n.T(`Edit a cluster configuration.
This command changes the instancegroup desired configuration in the registry.
This command changes the instance group desired configuration in the registry.
To set your preferred editor, you can define the EDITOR environment variable.
When you have done this, kOps will use the editor that you have set.
kops edit does not update the cloud resources, to apply the changes use "kops update cluster".`))
kops edit does not update the cloud resources; to apply the changes use ` + pretty.Bash("kops update cluster") + `.`))
editInstancegroupExample = templates.Examples(i18n.T(`
# Edit an instancegroup desired configuration.
@ -63,6 +67,11 @@ var (
type EditInstanceGroupOptions struct {
ClusterName string
GroupName string
// Sets allows setting values directly in the spec.
Sets []string
// Unsets allows unsetting values directly in the spec.
Unsets []string
}
func NewCmdEditInstanceGroup(f *util.Factory, out io.Writer) *cobra.Command {
@ -99,6 +108,17 @@ func NewCmdEditInstanceGroup(f *util.Factory, out io.Writer) *cobra.Command {
},
}
if featureflag.SpecOverrideFlag.Enabled() {
cmd.Flags().StringSliceVar(&options.Sets, "set", options.Sets, "Directly set values in the spec")
cmd.RegisterFlagCompletionFunc("set", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return nil, cobra.ShellCompDirectiveNoFileComp
})
cmd.Flags().StringSliceVar(&options.Unsets, "unset", options.Unsets, "Directly unset values in the spec")
cmd.RegisterFlagCompletionFunc("unset", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return nil, cobra.ShellCompDirectiveNoFileComp
})
}
return cmd
}
@ -128,6 +148,25 @@ func RunEditInstanceGroup(ctx context.Context, f *util.Factory, out io.Writer, o
return fmt.Errorf("InstanceGroup %q not found", groupName)
}
if len(options.Unsets)+len(options.Sets) > 0 {
newGroup := oldGroup.DeepCopy()
if err := commands.UnsetInstancegroupFields(options.Unsets, newGroup); err != nil {
return err
}
if err := commands.SetInstancegroupFields(options.Sets, newGroup); err != nil {
return err
}
failure, err := updateInstanceGroup(ctx, clientset, channel, cluster, oldGroup, newGroup)
if err != nil {
return err
}
if failure != "" {
return fmt.Errorf("%s", failure)
}
return nil
}
var (
editor = editor.NewDefaultEditor(commandutils.EditorEnvs)
)
@ -226,54 +265,53 @@ func RunEditInstanceGroup(ctx context.Context, f *util.Factory, out io.Writer, o
continue
}
cloud, err := cloudup.BuildCloud(cluster)
if err != nil {
return err
}
fullGroup, err := cloudup.PopulateInstanceGroupSpec(cluster, newGroup, cloud, channel)
if err != nil {
results = editResults{
file: file,
}
results.header.addError(fmt.Sprintf("error populating instance group spec: %s", err))
containsError = true
continue
}
// We need the full cluster spec to perform deep validation
// Note that we don't write it back though
err = cloudup.PerformAssignments(cluster, cloud)
if err != nil {
return preservedFile(fmt.Errorf("error populating configuration: %v", err), file, out)
}
assetBuilder := assets.NewAssetBuilder(cluster, false)
fullCluster, err := cloudup.PopulateClusterSpec(clientset, cluster, cloud, assetBuilder)
if err != nil {
results = editResults{
file: file,
}
results.header.addError(fmt.Sprintf("error populating cluster spec: %s", err))
containsError = true
continue
}
err = validation.CrossValidateInstanceGroup(fullGroup, fullCluster, cloud).ToAggregate()
if err != nil {
results = editResults{
file: file,
}
results.header.addError(fmt.Sprintf("validation failed: %s", err))
containsError = true
continue
}
// Note we perform as much validation as we can, before writing a bad config
_, err = clientset.InstanceGroupsFor(cluster).Update(ctx, fullGroup, metav1.UpdateOptions{})
failure, err := updateInstanceGroup(ctx, clientset, channel, cluster, oldGroup, newGroup)
if err != nil {
return preservedFile(err, file, out)
}
if failure != "" {
results = editResults{
file: file,
}
results.header.addError(failure)
containsError = true
continue
}
return nil
}
}
func updateInstanceGroup(ctx context.Context, clientset simple.Clientset, channel *api.Channel, cluster *api.Cluster, oldGroup, newGroup *api.InstanceGroup) (string, error) {
cloud, err := cloudup.BuildCloud(cluster)
if err != nil {
return "", err
}
fullGroup, err := cloudup.PopulateInstanceGroupSpec(cluster, newGroup, cloud, channel)
if err != nil {
return fmt.Sprintf("error populating instance group spec: %s", err), nil
}
// We need the full cluster spec to perform deep validation
// Note that we don't write it back though
err = cloudup.PerformAssignments(cluster, cloud)
if err != nil {
return "", fmt.Errorf("error populating configuration: %v", err)
}
assetBuilder := assets.NewAssetBuilder(cluster, false)
fullCluster, err := cloudup.PopulateClusterSpec(clientset, cluster, cloud, assetBuilder)
if err != nil {
return fmt.Sprintf("error populating cluster spec: %s", err), nil
}
err = validation.CrossValidateInstanceGroup(fullGroup, fullCluster, cloud).ToAggregate()
if err != nil {
return fmt.Sprintf("validation failed: %s", err), nil
}
// Note we perform as much validation as we can, before writing a bad config
_, err = clientset.InstanceGroupsFor(cluster).Update(ctx, fullGroup, metav1.UpdateOptions{})
return "", err
}

View File

@ -32,6 +32,7 @@ import (
"k8s.io/kops/cloudmock/aws/mockec2"
gcemock "k8s.io/kops/cloudmock/gce"
"k8s.io/kops/cmd/kops/util"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/commands"
"k8s.io/kops/pkg/featureflag"
"k8s.io/kops/pkg/testutils"
@ -219,12 +220,17 @@ func runLifecycleTest(h *testutils.IntegrationTestHarness, o *LifecycleTestOptio
}
for _, overrideBatch := range overrides {
t.Logf("overriding cluster values %v\n", overrideBatch)
setClusterOptions := &commands.SetClusterOptions{
Fields: overrideBatch,
ClusterName: o.ClusterName,
instanceGroups, err := commands.ReadAllInstanceGroups(ctx, clientset, cluster)
if err != nil {
t.Fatalf("error reading instance groups: %v", err)
}
if err := commands.RunSetCluster(ctx, factory, nil, nil, setClusterOptions); err != nil {
t.Fatalf("error applying overrides: %v", err)
if err := commands.SetClusterFields(overrideBatch, cluster); err != nil {
t.Fatalf("error setting cluster fields: %v", err)
}
if err := commands.UpdateCluster(ctx, clientset, cluster, instanceGroups); err != nil {
t.Fatalf("error updating cluster: %v", err)
}
updateEnsureNoChanges(ctx, t, factory, o.ClusterName, stdout)
}
@ -242,14 +248,29 @@ func runLifecycleTest(h *testutils.IntegrationTestHarness, o *LifecycleTestOptio
for _, overrideBatch := range overrides {
t.Logf("overriding instance group values (%v) %v\n", ig.Name, overrideBatch)
setIGOptions := &commands.SetInstanceGroupOptions{
Fields: overrideBatch,
ClusterName: o.ClusterName,
InstanceGroupName: ig.Name,
instanceGroups, err := commands.ReadAllInstanceGroups(ctx, clientset, cluster)
if err != nil {
t.Fatalf("error reading instance groups: %v", err)
}
if err := commands.RunSetInstancegroup(ctx, factory, nil, nil, setIGOptions); err != nil {
var instanceGroupToUpdate *kops.InstanceGroup
for _, instanceGroup := range instanceGroups {
if instanceGroup.GetName() == ig.Name {
instanceGroupToUpdate = instanceGroup
}
}
if instanceGroupToUpdate == nil {
t.Fatalf("unable to find instance group with name %q", ig.Name)
}
err = commands.SetInstancegroupFields(overrideBatch, instanceGroupToUpdate)
if err != nil {
t.Fatalf("error applying overrides: %v", err)
}
err = commands.UpdateInstanceGroup(ctx, clientset, cluster, instanceGroups, instanceGroupToUpdate)
if err != nil {
t.Fatalf("error updating instance groups: %v", err)
}
updateEnsureNoChanges(ctx, t, factory, o.ClusterName, stdout)
}
}

View File

@ -154,10 +154,8 @@ func NewCmdRoot(f *util.Factory, out io.Writer) *cobra.Command {
cmd.AddCommand(NewCmdPromote(f, out))
cmd.AddCommand(NewCmdReplace(f, out))
cmd.AddCommand(NewCmdRollingUpdate(f, out))
cmd.AddCommand(NewCmdSet(f, out))
cmd.AddCommand(NewCmdToolbox(f, out))
cmd.AddCommand(NewCmdTrust(f, out))
cmd.AddCommand(NewCmdUnset(f, out))
cmd.AddCommand(NewCmdUpdate(f, out))
cmd.AddCommand(NewCmdUpgrade(f, out))
cmd.AddCommand(NewCmdValidate(f, out))

View File

@ -1,54 +0,0 @@
/*
Copyright 2019 The Kubernetes Authors.
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 main
import (
"io"
"github.com/spf13/cobra"
"k8s.io/kops/cmd/kops/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
)
var (
setLong = templates.LongDesc(i18n.T(`Set a configuration field.
kops set does not update the cloud resources; to apply the changes use "kops update cluster".
`))
setExample = templates.Examples(i18n.T(`
# Set cluster to run kubernetes version 1.17.0
kops set cluster k8s-cluster.example.com spec.kubernetesVersion=1.17.0
kops set instancegroup --name k8s-cluster.example.com nodes-1a spec.maxSize=4
`))
)
func NewCmdSet(f *util.Factory, out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "set",
Short: i18n.T("Set fields on clusters and other resources."),
Long: setLong,
Example: setExample,
}
// create subcommands
cmd.AddCommand(NewCmdSetCluster(f, out))
cmd.AddCommand(NewCmdSetInstancegroup(f, out))
return cmd
}

View File

@ -1,83 +0,0 @@
/*
Copyright 2019 The Kubernetes Authors.
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 main
import (
"context"
"fmt"
"io"
"strings"
"github.com/spf13/cobra"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"k8s.io/kops/cmd/kops/util"
"k8s.io/kops/pkg/commands"
)
var (
setClusterLong = templates.LongDesc(i18n.T(`Set a cluster field value.
This command changes the desired cluster configuration in the registry.
kops set does not update the cloud resources; to apply the changes use "kops update cluster".`))
setClusterExample = templates.Examples(i18n.T(`
# Set cluster to run kubernetes version 1.17.0
kops set cluster k8s.cluster.site spec.kubernetesVersion=1.17.0
`))
)
// NewCmdSetCluster builds a cobra command for the kops set cluster command
func NewCmdSetCluster(f *util.Factory, out io.Writer) *cobra.Command {
options := &commands.SetClusterOptions{}
cmd := &cobra.Command{
Use: "cluster",
Short: i18n.T("Set cluster fields."),
Long: setClusterLong,
Example: setClusterExample,
Run: func(cmd *cobra.Command, args []string) {
ctx := context.TODO()
for i, arg := range args {
index := strings.Index(arg, "=")
if i == 0 && index == -1 {
options.ClusterName = arg
} else {
if index == -1 {
exitWithError(fmt.Errorf("unrecognized parameter %q (missing '=')", arg))
return
}
options.Fields = append(options.Fields, arg)
}
}
if options.ClusterName == "" {
options.ClusterName = rootCommand.ClusterName(true)
}
if err := commands.RunSetCluster(ctx, f, cmd, out, options); err != nil {
exitWithError(err)
}
},
}
return cmd
}

View File

@ -1,85 +0,0 @@
/*
Copyright 2021 The Kubernetes Authors.
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 main
import (
"context"
"fmt"
"io"
"strings"
"github.com/spf13/cobra"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"k8s.io/kops/cmd/kops/util"
"k8s.io/kops/pkg/commands"
)
var (
setInstancegroupLong = templates.LongDesc(i18n.T(`Set an instance group field value.
This command changes the desired instance group configuration in the registry.
kops set does not update the cloud resources; to apply the changes use "kops update cluster".`))
setInstancegroupExample = templates.Examples(i18n.T(`
# Set instance group to run image custom-ami-image
kops set instancegroup --name k8s-cluster.example.com nodes spec.image=custom-ami-image
`))
)
// NewCmdSetInstancegroup builds a cobra command for the kops set instancegroup command.
func NewCmdSetInstancegroup(f *util.Factory, out io.Writer) *cobra.Command {
options := &commands.SetInstanceGroupOptions{}
cmd := &cobra.Command{
Use: "instancegroup",
Aliases: []string{"instancegroups", "ig"},
Short: i18n.T("Set instancegroup fields."),
Long: setInstancegroupLong,
Example: setInstancegroupExample,
Run: func(cmd *cobra.Command, args []string) {
ctx := context.TODO()
for i, arg := range args {
index := strings.Index(arg, "=")
if i == 0 {
if index != -1 {
exitWithError(fmt.Errorf("Specify name of instance group to edit"))
}
options.InstanceGroupName = arg
} else {
if index == -1 {
exitWithError(fmt.Errorf("unrecognized parameter %q (missing '=')", arg))
return
}
options.Fields = append(options.Fields, arg)
}
}
options.ClusterName = rootCommand.ClusterName(true)
if err := commands.RunSetInstancegroup(ctx, f, cmd, out, options); err != nil {
exitWithError(err)
}
},
}
return cmd
}

View File

@ -1,53 +0,0 @@
/*
Copyright 2021 The Kubernetes Authors.
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 main
import (
"io"
"github.com/spf13/cobra"
"k8s.io/kops/cmd/kops/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
)
var (
unsetLong = templates.LongDesc(i18n.T(`Unset a configuration field.
kops unset does not update the cloud resources; to apply the changes use "kops update cluster".
`))
unsetExample = templates.Examples(i18n.T(`
kops unset cluster k8s-cluster.example.com spec.iam.allowContainerRegistry
kops unset instancegroup --name k8s-cluster.example.com nodes-1a spec.maxSize
`))
)
func NewCmdUnset(f *util.Factory, out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "unset",
Short: i18n.T("Unset fields on clusters and other resources."),
Long: unsetLong,
Example: unsetExample,
}
// create subcommands
cmd.AddCommand(NewCmdUnsetCluster(f, out))
cmd.AddCommand(NewCmdUnsetInstancegroup(f, out))
return cmd
}

View File

@ -1,75 +0,0 @@
/*
Copyright 2019 The Kubernetes Authors.
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 main
import (
"context"
"io"
"strings"
"github.com/spf13/cobra"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"k8s.io/kops/cmd/kops/util"
"k8s.io/kops/pkg/commands"
)
var (
unsetClusterLong = templates.LongDesc(i18n.T(`Unset a cluster field value.
This command changes the desired cluster configuration in the registry.
kops unset does not update the cloud resources; to apply the changes use "kops update cluster".`))
unsetClusterExample = templates.Examples(i18n.T(`
kops unset cluster k8s-cluster.example.com spec.iam.allowContainerRegistry
`))
)
// NewCmdUnsetCluster builds a cobra command for the kops unset cluster command
func NewCmdUnsetCluster(f *util.Factory, out io.Writer) *cobra.Command {
options := &commands.UnsetClusterOptions{}
cmd := &cobra.Command{
Use: "cluster",
Short: i18n.T("Unset cluster fields."),
Long: unsetClusterLong,
Example: unsetClusterExample,
Run: func(cmd *cobra.Command, args []string) {
ctx := context.TODO()
for i, arg := range args {
if i == 0 && !strings.HasPrefix(arg, "spec.") && !strings.HasPrefix(arg, "cluster.") {
options.ClusterName = arg
} else {
options.Fields = append(options.Fields, arg)
}
}
if options.ClusterName == "" {
options.ClusterName = rootCommand.ClusterName(true)
}
if err := commands.RunUnsetCluster(ctx, f, cmd, out, options); err != nil {
exitWithError(err)
}
},
}
return cmd
}

View File

@ -1,75 +0,0 @@
/*
Copyright 2021 The Kubernetes Authors.
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 main
import (
"context"
"io"
"strings"
"github.com/spf13/cobra"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"k8s.io/kops/cmd/kops/util"
"k8s.io/kops/pkg/commands"
)
var (
unsetInstancegroupLong = templates.LongDesc(i18n.T(`Unset an instance group field value.
This command changes the desired instance group configuration in the registry.
kops unset does not update the cloud resources; to apply the changes use "kops update cluster".`))
unsetInstancegroupExample = templates.Examples(i18n.T(`
# Set instance group to run default image
kops unset instancegroup --name k8s-cluster.example.com nodes spec.image
`))
)
// NewCmdUnsetInstancegroup builds a cobra command for the kops set instancegroup command.
func NewCmdUnsetInstancegroup(f *util.Factory, out io.Writer) *cobra.Command {
options := &commands.UnsetInstanceGroupOptions{}
cmd := &cobra.Command{
Use: "instancegroup",
Aliases: []string{"instancegroups", "ig"},
Short: i18n.T("Unset instancegroup fields."),
Long: unsetInstancegroupLong,
Example: unsetInstancegroupExample,
Run: func(cmd *cobra.Command, args []string) {
ctx := context.TODO()
for i, arg := range args {
if i == 0 && !strings.HasPrefix(arg, "spec.") && !strings.HasPrefix(arg, "instancegroup.") {
options.InstanceGroupName = arg
} else {
options.Fields = append(options.Fields, arg)
}
}
options.ClusterName = rootCommand.ClusterName(true)
if err := commands.RunUnsetInstancegroup(ctx, f, cmd, out, options); err != nil {
exitWithError(err)
}
},
}
return cmd
}

2
docs/cli/kops.md generated
View File

@ -48,10 +48,8 @@ kOps is Kubernetes Operations.
* [kops promote](kops_promote.md) - Promote a resource.
* [kops replace](kops_replace.md) - Replace cluster resources.
* [kops rolling-update](kops_rolling-update.md) - Rolling update a cluster.
* [kops set](kops_set.md) - Set fields on clusters and other resources.
* [kops toolbox](kops_toolbox.md) - Misc infrequently used commands.
* [kops trust](kops_trust.md) - Trust keypairs.
* [kops unset](kops_unset.md) - Unset fields on clusters and other resources.
* [kops update](kops_update.md) - Update a cluster.
* [kops upgrade](kops_upgrade.md) - Upgrade a kubernetes cluster.
* [kops validate](kops_validate.md) - Validate a kOps cluster.

View File

@ -9,11 +9,12 @@ Edit cluster.
Edit a cluster configuration.
This command changes the desired cluster configuration in the registry.
This command changes the desired cluster configuration in the registry.
To set your preferred editor, you can define the EDITOR environment variable. When you have done this, kOps will use the editor that you have set.
To set your preferred editor, you can define the EDITOR environment variable.
When you have done this, kOps will use the editor that you have set.
kops edit does not update the cloud resources, to apply the changes usekops update cluster .
kops edit does not update the cloud resources; to apply the changes use `kops update cluster`.
```
kops edit cluster [CLUSTER] [flags]

View File

@ -9,11 +9,12 @@ Edit instancegroup.
Edit a cluster configuration.
This command changes the instancegroup desired configuration in the registry.
This command changes the instance group desired configuration in the registry.
To set your preferred editor, you can define the EDITOR environment variable. When you have done this, kOps will use the editor that you have set.
To set your preferred editor, you can define the EDITOR environment variable.
When you have done this, kOps will use the editor that you have set.
kops edit does not update the cloud resources, to apply the changes use "kops update cluster".
kops edit does not update the cloud resources; to apply the changes use `kops update cluster`.
```
kops edit instancegroup INSTANCE_GROUP [flags]

54
docs/cli/kops_set.md generated
View File

@ -1,54 +0,0 @@
<!--- This file is automatically generated by make gen-cli-docs; changes should be made in the go CLI command code (under cmd/kops) -->
## kops set
Set fields on clusters and other resources.
### Synopsis
Set a configuration field.
kops set does not update the cloud resources; to apply the changes use "kops update cluster".
### Examples
```
# Set cluster to run kubernetes version 1.17.0
kops set cluster k8s-cluster.example.com spec.kubernetesVersion=1.17.0
kops set instancegroup --name k8s-cluster.example.com nodes-1a spec.maxSize=4
```
### Options
```
-h, --help help for set
```
### Options inherited from parent commands
```
--add_dir_header If true, adds the file directory to the header of the log messages
--alsologtostderr log to standard error as well as files
--config string yaml config file (default is $HOME/.kops.yaml)
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
--log_dir string If non-empty, write log files in this directory
--log_file string If non-empty, use this log file
--log_file_max_size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
--logtostderr log to standard error instead of files (default true)
--name string Name of cluster. Overrides KOPS_CLUSTER_NAME environment variable
--one_output If true, only write logs to their native severity level (vs also writing to each lower severity level)
--skip_headers If true, avoid header prefixes in the log messages
--skip_log_headers If true, avoid headers when opening log files
--state string Location of state storage (kops 'config' file). Overrides KOPS_STATE_STORE environment variable
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
-v, --v Level number for the log level verbosity
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
```
### SEE ALSO
* [kops](kops.md) - kOps is Kubernetes Operations.
* [kops set cluster](kops_set_cluster.md) - Set cluster fields.
* [kops set instancegroup](kops_set_instancegroup.md) - Set instancegroup fields.

View File

@ -1,57 +0,0 @@
<!--- This file is automatically generated by make gen-cli-docs; changes should be made in the go CLI command code (under cmd/kops) -->
## kops set cluster
Set cluster fields.
### Synopsis
Set a cluster field value.
This command changes the desired cluster configuration in the registry.
kops set does not update the cloud resources; to apply the changes use "kops update cluster".
```
kops set cluster [flags]
```
### Examples
```
# Set cluster to run kubernetes version 1.17.0
kops set cluster k8s.cluster.site spec.kubernetesVersion=1.17.0
```
### Options
```
-h, --help help for cluster
```
### Options inherited from parent commands
```
--add_dir_header If true, adds the file directory to the header of the log messages
--alsologtostderr log to standard error as well as files
--config string yaml config file (default is $HOME/.kops.yaml)
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
--log_dir string If non-empty, write log files in this directory
--log_file string If non-empty, use this log file
--log_file_max_size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
--logtostderr log to standard error instead of files (default true)
--name string Name of cluster. Overrides KOPS_CLUSTER_NAME environment variable
--one_output If true, only write logs to their native severity level (vs also writing to each lower severity level)
--skip_headers If true, avoid header prefixes in the log messages
--skip_log_headers If true, avoid headers when opening log files
--state string Location of state storage (kops 'config' file). Overrides KOPS_STATE_STORE environment variable
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
-v, --v Level number for the log level verbosity
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
```
### SEE ALSO
* [kops set](kops_set.md) - Set fields on clusters and other resources.

View File

@ -1,57 +0,0 @@
<!--- This file is automatically generated by make gen-cli-docs; changes should be made in the go CLI command code (under cmd/kops) -->
## kops set instancegroup
Set instancegroup fields.
### Synopsis
Set an instance group field value.
This command changes the desired instance group configuration in the registry.
kops set does not update the cloud resources; to apply the changes use "kops update cluster".
```
kops set instancegroup [flags]
```
### Examples
```
# Set instance group to run image custom-ami-image
kops set instancegroup --name k8s-cluster.example.com nodes spec.image=custom-ami-image
```
### Options
```
-h, --help help for instancegroup
```
### Options inherited from parent commands
```
--add_dir_header If true, adds the file directory to the header of the log messages
--alsologtostderr log to standard error as well as files
--config string yaml config file (default is $HOME/.kops.yaml)
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
--log_dir string If non-empty, write log files in this directory
--log_file string If non-empty, use this log file
--log_file_max_size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
--logtostderr log to standard error instead of files (default true)
--name string Name of cluster. Overrides KOPS_CLUSTER_NAME environment variable
--one_output If true, only write logs to their native severity level (vs also writing to each lower severity level)
--skip_headers If true, avoid header prefixes in the log messages
--skip_log_headers If true, avoid headers when opening log files
--state string Location of state storage (kops 'config' file). Overrides KOPS_STATE_STORE environment variable
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
-v, --v Level number for the log level verbosity
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
```
### SEE ALSO
* [kops set](kops_set.md) - Set fields on clusters and other resources.

53
docs/cli/kops_unset.md generated
View File

@ -1,53 +0,0 @@
<!--- This file is automatically generated by make gen-cli-docs; changes should be made in the go CLI command code (under cmd/kops) -->
## kops unset
Unset fields on clusters and other resources.
### Synopsis
Unset a configuration field.
kops unset does not update the cloud resources; to apply the changes use "kops update cluster".
### Examples
```
kops unset cluster k8s-cluster.example.com spec.iam.allowContainerRegistry
kops unset instancegroup --name k8s-cluster.example.com nodes-1a spec.maxSize
```
### Options
```
-h, --help help for unset
```
### Options inherited from parent commands
```
--add_dir_header If true, adds the file directory to the header of the log messages
--alsologtostderr log to standard error as well as files
--config string yaml config file (default is $HOME/.kops.yaml)
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
--log_dir string If non-empty, write log files in this directory
--log_file string If non-empty, use this log file
--log_file_max_size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
--logtostderr log to standard error instead of files (default true)
--name string Name of cluster. Overrides KOPS_CLUSTER_NAME environment variable
--one_output If true, only write logs to their native severity level (vs also writing to each lower severity level)
--skip_headers If true, avoid header prefixes in the log messages
--skip_log_headers If true, avoid headers when opening log files
--state string Location of state storage (kops 'config' file). Overrides KOPS_STATE_STORE environment variable
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
-v, --v Level number for the log level verbosity
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
```
### SEE ALSO
* [kops](kops.md) - kOps is Kubernetes Operations.
* [kops unset cluster](kops_unset_cluster.md) - Unset cluster fields.
* [kops unset instancegroup](kops_unset_instancegroup.md) - Unset instancegroup fields.

View File

@ -1,56 +0,0 @@
<!--- This file is automatically generated by make gen-cli-docs; changes should be made in the go CLI command code (under cmd/kops) -->
## kops unset cluster
Unset cluster fields.
### Synopsis
Unset a cluster field value.
This command changes the desired cluster configuration in the registry.
kops unset does not update the cloud resources; to apply the changes use "kops update cluster".
```
kops unset cluster [flags]
```
### Examples
```
kops unset cluster k8s-cluster.example.com spec.iam.allowContainerRegistry
```
### Options
```
-h, --help help for cluster
```
### Options inherited from parent commands
```
--add_dir_header If true, adds the file directory to the header of the log messages
--alsologtostderr log to standard error as well as files
--config string yaml config file (default is $HOME/.kops.yaml)
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
--log_dir string If non-empty, write log files in this directory
--log_file string If non-empty, use this log file
--log_file_max_size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
--logtostderr log to standard error instead of files (default true)
--name string Name of cluster. Overrides KOPS_CLUSTER_NAME environment variable
--one_output If true, only write logs to their native severity level (vs also writing to each lower severity level)
--skip_headers If true, avoid header prefixes in the log messages
--skip_log_headers If true, avoid headers when opening log files
--state string Location of state storage (kops 'config' file). Overrides KOPS_STATE_STORE environment variable
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
-v, --v Level number for the log level verbosity
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
```
### SEE ALSO
* [kops unset](kops_unset.md) - Unset fields on clusters and other resources.

View File

@ -1,57 +0,0 @@
<!--- This file is automatically generated by make gen-cli-docs; changes should be made in the go CLI command code (under cmd/kops) -->
## kops unset instancegroup
Unset instancegroup fields.
### Synopsis
Unset an instance group field value.
This command changes the desired instance group configuration in the registry.
kops unset does not update the cloud resources; to apply the changes use "kops update cluster".
```
kops unset instancegroup [flags]
```
### Examples
```
# Set instance group to run default image
kops unset instancegroup --name k8s-cluster.example.com nodes spec.image
```
### Options
```
-h, --help help for instancegroup
```
### Options inherited from parent commands
```
--add_dir_header If true, adds the file directory to the header of the log messages
--alsologtostderr log to standard error as well as files
--config string yaml config file (default is $HOME/.kops.yaml)
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
--log_dir string If non-empty, write log files in this directory
--log_file string If non-empty, use this log file
--log_file_max_size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
--logtostderr log to standard error instead of files (default true)
--name string Name of cluster. Overrides KOPS_CLUSTER_NAME environment variable
--one_output If true, only write logs to their native severity level (vs also writing to each lower severity level)
--skip_headers If true, avoid header prefixes in the log messages
--skip_log_headers If true, avoid headers when opening log files
--state string Location of state storage (kops 'config' file). Overrides KOPS_STATE_STORE environment variable
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
-v, --v Level number for the log level verbosity
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
```
### SEE ALSO
* [kops unset](kops_unset.md) - Unset fields on clusters and other resources.

View File

@ -79,7 +79,7 @@ If you don't already have TLS enabled with etcd, you can adopt etcd-manager befo
kOps 1.12 & kubernetes 1.12 by running:
```bash
kops set cluster cluster.spec.etcdClusters[*].provider=manager
kops edit cluster --set=cluster.spec.etcdClusters[*].provider=manager
```
Then you can proceed to update to kOps 1.12 & kubernetes 1.12, as this becomes the default.
@ -89,7 +89,7 @@ Then you can proceed to update to kOps 1.12 & kubernetes 1.12, as this becomes t
To delay adopting etcd-manager with kOps 1.12, specify the provider as type `legacy`:
```bash
kops set cluster cluster.spec.etcdClusters[*].provider=legacy
kops edit cluster --set=cluster.spec.etcdClusters[*].provider=legacy
```
To remove, `kops edit` your cluster and delete the `provider: Legacy` lines from both etcdCluster blocks.
@ -99,7 +99,7 @@ To remove, `kops edit` your cluster and delete the `provider: Legacy` lines from
To delay adopting etcd3 with kOps 1.12, specify the etcd version as 2.2.1
```bash
kops set cluster cluster.spec.etcdClusters[*].version=2.2.1
kops edit cluster --set=cluster.spec.etcdClusters[*].version=2.2.1
```
To remove, `kops edit` your cluster and delete the `version: 2.2.1` lines from both etcdCluster blocks.

View File

@ -60,10 +60,8 @@ nav:
- kops promote: "cli/kops_promote.md"
- kops replace: "cli/kops_replace.md"
- kops rolling-update: "cli/kops_rolling-update.md"
- kops set: "cli/kops_set.md"
- kops toolbox: "cli/kops_toolbox.md"
- kops trust: "cli/kops_trust.md"
- kops unset: "cli/kops_unset.md"
- kops update: "cli/kops_update.md"
- kops upgrade: "cli/kops_upgrade.md"
- kops validate: "cli/kops_validate.md"

View File

@ -21,12 +21,10 @@ go_library(
"//pkg/assets:go_default_library",
"//pkg/client/simple:go_default_library",
"//pkg/commands/helpers:go_default_library",
"//pkg/featureflag:go_default_library",
"//upup/pkg/fi/cloudup:go_default_library",
"//util/pkg/reflectutils:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/k8s.io/kubectl/pkg/util/i18n:go_default_library",
"//vendor/k8s.io/kubectl/pkg/util/templates:go_default_library",
],

View File

@ -17,61 +17,13 @@ limitations under the License.
package commands
import (
"context"
"fmt"
"io"
"strings"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/kops/cmd/kops/util"
api "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/featureflag"
"k8s.io/kops/util/pkg/reflectutils"
)
type SetClusterOptions struct {
Fields []string
ClusterName string
}
// RunSetCluster implements the set cluster command logic
func RunSetCluster(ctx context.Context, f *util.Factory, cmd *cobra.Command, out io.Writer, options *SetClusterOptions) error {
if !featureflag.SpecOverrideFlag.Enabled() {
return fmt.Errorf("set cluster command is current feature gated; set `export KOPS_FEATURE_FLAGS=SpecOverrideFlag`")
}
if options.ClusterName == "" {
return field.Required(field.NewPath("clusterName"), "Cluster name is required")
}
clientset, err := f.Clientset()
if err != nil {
return err
}
cluster, err := clientset.GetCluster(ctx, options.ClusterName)
if err != nil {
return err
}
instanceGroups, err := ReadAllInstanceGroups(ctx, clientset, cluster)
if err != nil {
return err
}
if err := SetClusterFields(options.Fields, cluster); err != nil {
return err
}
if err := UpdateCluster(ctx, clientset, cluster, instanceGroups); err != nil {
return err
}
return nil
}
// SetClusterFields sets field values in the cluster
func SetClusterFields(fields []string, cluster *api.Cluster) error {
for _, field := range fields {

View File

@ -17,78 +17,13 @@ limitations under the License.
package commands
import (
"context"
"fmt"
"io"
"strings"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/kops/cmd/kops/util"
api "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/featureflag"
"k8s.io/kops/util/pkg/reflectutils"
)
// SetInstanceGroupOptions contains the options for setting configuration on an
// instance group.
type SetInstanceGroupOptions struct {
Fields []string
ClusterName string
InstanceGroupName string
}
// RunSetInstancegroup implements the set instancegroup command logic.
func RunSetInstancegroup(ctx context.Context, f *util.Factory, cmd *cobra.Command, out io.Writer, options *SetInstanceGroupOptions) error {
if !featureflag.SpecOverrideFlag.Enabled() {
return fmt.Errorf("set instancegroup is currently feature gated; set `export KOPS_FEATURE_FLAGS=SpecOverrideFlag`")
}
if options.ClusterName == "" {
return field.Required(field.NewPath("clusterName"), "Cluster name is required")
}
if options.InstanceGroupName == "" {
return field.Required(field.NewPath("instancegroupName"), "Instance Group name is required")
}
clientset, err := f.Clientset()
if err != nil {
return err
}
cluster, err := clientset.GetCluster(ctx, options.ClusterName)
if err != nil {
return err
}
instanceGroups, err := ReadAllInstanceGroups(ctx, clientset, cluster)
if err != nil {
return err
}
var instanceGroupToUpdate *api.InstanceGroup
for _, instanceGroup := range instanceGroups {
if instanceGroup.GetName() == options.InstanceGroupName {
instanceGroupToUpdate = instanceGroup
}
}
if instanceGroupToUpdate == nil {
return fmt.Errorf("unable to find instance group with name %q", options.InstanceGroupName)
}
err = SetInstancegroupFields(options.Fields, instanceGroupToUpdate)
if err != nil {
return err
}
err = UpdateInstanceGroup(ctx, clientset, cluster, instanceGroups, instanceGroupToUpdate)
if err != nil {
return err
}
return nil
}
// SetInstancegroupFields sets field values in the instance group.
func SetInstancegroupFields(fields []string, instanceGroup *api.InstanceGroup) error {
for _, field := range fields {

View File

@ -17,61 +17,12 @@ limitations under the License.
package commands
import (
"context"
"fmt"
"io"
"strings"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/kops/cmd/kops/util"
api "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/featureflag"
"k8s.io/kops/util/pkg/reflectutils"
)
type UnsetClusterOptions struct {
Fields []string
ClusterName string
}
// RunUnsetCluster implements the unset cluster command logic
func RunUnsetCluster(ctx context.Context, f *util.Factory, cmd *cobra.Command, out io.Writer, options *UnsetClusterOptions) error {
if !featureflag.SpecOverrideFlag.Enabled() {
return fmt.Errorf("unset cluster command is current feature gated; set `export KOPS_FEATURE_FLAGS=SpecOverrideFlag`")
}
if options.ClusterName == "" {
return field.Required(field.NewPath("clusterName"), "Cluster name is required")
}
clientset, err := f.Clientset()
if err != nil {
return err
}
cluster, err := clientset.GetCluster(ctx, options.ClusterName)
if err != nil {
return err
}
instanceGroups, err := ReadAllInstanceGroups(ctx, clientset, cluster)
if err != nil {
return err
}
if err := UnsetClusterFields(options.Fields, cluster); err != nil {
return err
}
if err := UpdateCluster(ctx, clientset, cluster, instanceGroups); err != nil {
return err
}
return nil
}
// UnsetClusterFields unsets field values in the cluster
func UnsetClusterFields(fields []string, cluster *api.Cluster) error {
for _, field := range fields {

View File

@ -17,78 +17,12 @@ limitations under the License.
package commands
import (
"context"
"fmt"
"io"
"strings"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/kops/cmd/kops/util"
api "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/featureflag"
"k8s.io/kops/util/pkg/reflectutils"
)
// UnsetInstanceGroupOptions contains the options for unsetting configuration on an
// instance group.
type UnsetInstanceGroupOptions struct {
Fields []string
ClusterName string
InstanceGroupName string
}
// RunUnsetInstancegroup implements the unset instancegroup command logic.
func RunUnsetInstancegroup(ctx context.Context, f *util.Factory, cmd *cobra.Command, out io.Writer, options *UnsetInstanceGroupOptions) error {
if !featureflag.SpecOverrideFlag.Enabled() {
return fmt.Errorf("unset instancegroup is currently feature gated; set `export KOPS_FEATURE_FLAGS=SpecOverrideFlag`")
}
if options.ClusterName == "" {
return field.Required(field.NewPath("clusterName"), "Cluster name is required")
}
if options.InstanceGroupName == "" {
return field.Required(field.NewPath("instancegroupName"), "Instance Group name is required")
}
clientset, err := f.Clientset()
if err != nil {
return err
}
cluster, err := clientset.GetCluster(ctx, options.ClusterName)
if err != nil {
return err
}
instanceGroups, err := ReadAllInstanceGroups(ctx, clientset, cluster)
if err != nil {
return err
}
var instanceGroupToUpdate *api.InstanceGroup
for _, instanceGroup := range instanceGroups {
if instanceGroup.GetName() == options.InstanceGroupName {
instanceGroupToUpdate = instanceGroup
}
}
if instanceGroupToUpdate == nil {
return fmt.Errorf("unable to find instance group with name %q", options.InstanceGroupName)
}
err = UnsetInstancegroupFields(options.Fields, instanceGroupToUpdate)
if err != nil {
return err
}
err = UpdateInstanceGroup(ctx, clientset, cluster, instanceGroups, instanceGroupToUpdate)
if err != nil {
return err
}
return nil
}
// UnsetInstancegroupFields sets field values in the instance group.
func UnsetInstancegroupFields(fields []string, instanceGroup *api.InstanceGroup) error {
for _, field := range fields {

View File

@ -47,7 +47,7 @@ KOPS=$(kops-acquire-latest)
cp "${KOPS}" "${WORKSPACE}/kops"
# Switch to queue mode. This should remove the DS and install a Deployment instead
kops set cluster "${CLUSTER_NAME}" "cluster.spec.nodeTerminationHandler.enableSQSTerminationDraining=true"
kops edit cluster "${CLUSTER_NAME}" "--set=cluster.spec.nodeTerminationHandler.enableSQSTerminationDraining=true"
# allow downgrade is a bug where the version written to VFS is not the same as the running version.
kops update cluster --allow-kops-downgrade

View File

@ -52,7 +52,7 @@ KOPS_B=$(kops-download-from-base)
KOPS="${KOPS_B}"
"${KOPS_B}" set cluster "${CLUSTER_NAME}" "cluster.spec.kubernetesVersion=${K8S_VERSION_B}"
"${KOPS_B}" edit cluster "${CLUSTER_NAME}" "--set=cluster.spec.kubernetesVersion=${K8S_VERSION_B}"
"${KOPS_B}" update cluster
"${KOPS_B}" update cluster --admin --yes