Skip to content

Commit 3784fb3

Browse files
spewk8s-ci-robot
authored andcommitted
Add 'cluster', 'namespace', and 'user' options to delete command. Enhance delete to load provider components from cluster. (#384)
1 parent 3d9767c commit 3784fb3

File tree

10 files changed

+98
-71
lines changed

10 files changed

+98
-71
lines changed

clusterctl/clusterdeployer/clientfactory.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,5 @@ func (f *clientFactory) NewClusterClientFromKubeconfig(kubeconfig string) (Clust
3333
}
3434

3535
func (f *clientFactory) NewCoreClientsetFromKubeconfigFile(kubeconfigPath string) (*kubernetes.Clientset, error) {
36-
return clientcmd.NewCoreClientSetForDefaultSearchPath(kubeconfigPath)
36+
return clientcmd.NewCoreClientSetForDefaultSearchPath(kubeconfigPath, clientcmd.NewConfigOverrides())
3737
}

clusterctl/clusterdeployer/clusterclient.go

+33-16
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/golang/glog"
2929
apiv1 "k8s.io/api/core/v1"
3030
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31+
tcmd "k8s.io/client-go/tools/clientcmd"
3132
clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha1"
3233
"sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset"
3334
"sigs.k8s.io/cluster-api/pkg/clientcmd"
@@ -44,9 +45,10 @@ const (
4445
)
4546

4647
type clusterClient struct {
47-
clientSet clientset.Interface
48-
kubeconfigFile string
49-
closeFn func() error
48+
clientSet clientset.Interface
49+
kubeconfigFile string
50+
configOverrides tcmd.ConfigOverrides
51+
closeFn func() error
5052
}
5153

5254
// NewClusterClient creates and returns the address of a clusterClient, the kubeconfig argument is expected to be the string represenattion
@@ -57,7 +59,7 @@ func NewClusterClient(kubeconfig string) (*clusterClient, error) {
5759
return nil, err
5860
}
5961
defer ifErrRemove(&err, f)
60-
c, err := NewClusterClientFromFile(f)
62+
c, err := NewClusterClientFromDefaultSearchPath(f, clientcmd.NewConfigOverrides())
6163
if err != nil {
6264
return nil, err
6365
}
@@ -69,17 +71,18 @@ func (c *clusterClient) removeKubeconfigFile() error {
6971
return os.Remove(c.kubeconfigFile)
7072
}
7173

72-
// NewClusterClientFromFile creates and returns the address of a clusterClient, the kubeconfigFile argument is expected to be the path to a
74+
// NewClusterClientFromDefaultSearchPath creates and returns the address of a clusterClient, the kubeconfigFile argument is expected to be the path to a
7375
// valid kubeconfig file.
74-
func NewClusterClientFromFile(kubeconfigFile string) (*clusterClient, error) {
75-
c, err := clientcmd.NewClusterApiClientForDefaultSearchPath(kubeconfigFile)
76+
func NewClusterClientFromDefaultSearchPath(kubeconfigFile string, overrides tcmd.ConfigOverrides) (*clusterClient, error) {
77+
c, err := clientcmd.NewClusterApiClientForDefaultSearchPath(kubeconfigFile, overrides)
7678
if err != nil {
7779
return nil, err
7880
}
7981

8082
return &clusterClient{
81-
kubeconfigFile: kubeconfigFile,
82-
clientSet: c,
83+
kubeconfigFile: kubeconfigFile,
84+
clientSet: c,
85+
configOverrides: overrides,
8386
}, nil
8487
}
8588

@@ -169,16 +172,30 @@ func (c *clusterClient) WaitForClusterV1alpha1Ready() error {
169172
}
170173

171174
func (c *clusterClient) kubectlApply(manifest string) error {
172-
r := strings.NewReader(manifest)
173-
cmd := exec.Command("kubectl", "apply", "--kubeconfig", c.kubeconfigFile, "-f", "-")
174-
cmd.Stdin = r
175-
175+
cmd := exec.Command("kubectl", c.buildKubectlArgs("apply")...)
176+
cmd.Stdin = strings.NewReader(manifest)
176177
out, err := cmd.CombinedOutput()
177-
if err == nil {
178-
return nil
179-
} else {
178+
if err != nil {
180179
return fmt.Errorf("couldn't kubectl apply: %v, output: %s", err, string(out))
181180
}
181+
return nil
182+
}
183+
184+
func (c *clusterClient) buildKubectlArgs(commandName string) []string {
185+
args := []string{commandName}
186+
if c.kubeconfigFile != "" {
187+
args = append(args, "--kubeconfig", c.kubeconfigFile)
188+
}
189+
if c.configOverrides.Context.Cluster != "" {
190+
args = append(args, "--cluster", c.configOverrides.Context.Cluster)
191+
}
192+
if c.configOverrides.Context.Namespace != "" {
193+
args = append(args, "--namespace", c.configOverrides.Context.Namespace)
194+
}
195+
if c.configOverrides.Context.AuthInfo != "" {
196+
args = append(args, "--user", c.configOverrides.Context.AuthInfo)
197+
}
198+
return append(args, "-f", "-")
182199
}
183200

184201
func (c *clusterClient) waitForKubectlApply(manifest string) error {

clusterctl/cmd/delete_cluster.go

+34-6
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,22 @@ limitations under the License.
1717
package cmd
1818

1919
import (
20+
"fmt"
21+
22+
"k8s.io/api/core/v1"
23+
tcmd "k8s.io/client-go/tools/clientcmd"
24+
"sigs.k8s.io/cluster-api/clusterctl/providercomponents"
25+
"sigs.k8s.io/cluster-api/pkg/clientcmd"
26+
"sigs.k8s.io/cluster-api/pkg/errors"
27+
2028
"github.com/golang/glog"
2129
"github.com/spf13/cobra"
22-
"sigs.k8s.io/cluster-api/pkg/errors"
2330
)
2431

2532
type DeleteOptions struct {
26-
ClusterName string
27-
ProviderComponents string
33+
KubeconfigPath string
34+
ProviderComponents string
35+
KubeconfigOverrides tcmd.ConfigOverrides
2836
}
2937

3038
var do = &DeleteOptions{}
@@ -34,20 +42,40 @@ var deleteClusterCmd = &cobra.Command{
3442
Short: "Delete kubernetes cluster",
3543
Long: `Delete a kubernetes cluster with one command`,
3644
Run: func(cmd *cobra.Command, args []string) {
37-
if do.ClusterName == "" {
38-
exitWithHelp(cmd, "Please provide cluster name.")
39-
}
4045
if err := RunDelete(); err != nil {
4146
glog.Exit(err)
4247
}
4348
},
4449
}
4550

4651
func init() {
52+
deleteClusterCmd.Flags().StringVarP(&do.KubeconfigPath, "kubeconfig", "", "", "Path to the kubeconfig file to use for connecting to the cluster to be deleted, if empty, the default KUBECONFIG load path is used.")
4753
deleteClusterCmd.Flags().StringVarP(&do.ProviderComponents, "provider-components", "p", "", "A yaml file containing cluster api provider controllers and supporting objects, if empty the value is loaded from the cluster's configuration store.")
54+
// BindContextFlags will bind the flags cluster, namespace, and user
55+
tcmd.BindContextFlags(&do.KubeconfigOverrides.Context, deleteClusterCmd.Flags(), tcmd.RecommendedContextOverrideFlags(""))
4856
deleteCmd.AddCommand(deleteClusterCmd)
4957
}
5058

5159
func RunDelete() error {
60+
_, err := loadProviderComponents()
61+
if err != nil {
62+
return err
63+
}
5264
return errors.NotImplementedError
5365
}
66+
67+
func loadProviderComponents() (string, error) {
68+
coreClients, err := clientcmd.NewCoreClientSetForDefaultSearchPath(do.KubeconfigPath, do.KubeconfigOverrides)
69+
if err != nil {
70+
return "", fmt.Errorf("error creating core clients: %v", err)
71+
}
72+
pcStore := providercomponents.Store{
73+
ExplicitPath: do.ProviderComponents,
74+
ConfigMap: coreClients.CoreV1().ConfigMaps(v1.NamespaceDefault),
75+
}
76+
providerComponents, err := pcStore.Load()
77+
if err != nil {
78+
return "", fmt.Errorf("error when loading provider components: %v", err)
79+
}
80+
return providerComponents, nil
81+
}

clusterctl/main_integration_test.go

-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ func TestEmptyAndInvalidArgs(t *testing.T) {
6363
{"create cluster with no arguments with invalid flag", []string{"create", "cluster", "--invalid-flag"}, 1, "create-cluster-no-args-invalid-flag.golden"},
6464
{"delete with no arguments", []string{"delete"}, 0, "delete-no-args.golden"},
6565
{"delete with no arguments with invalid flag", []string{"delete", "--invalid-flag"}, 1, "delete-no-args-invalid-flag.golden"},
66-
{"delete cluster with no arguments", []string{"delete", "cluster"}, 1, "delete-cluster-no-args.golden"},
6766
{"delete cluster with no arguments with invalid flag", []string{"delete", "cluster", "--invalid-flag"}, 1, "delete-cluster-no-args-invalid-flag.golden"},
6867
{"validate with no arguments", []string{"validate"}, 0, "validate-no-args.golden"},
6968
{"validate with no arguments with invalid flag", []string{"validate", "--invalid-flag"}, 1, "validate-no-args-invalid-flag.golden"},

clusterctl/testdata/delete-cluster-no-args-invalid-flag.golden

+4
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@ Usage:
33
clusterctl delete cluster [flags]
44

55
Flags:
6+
--cluster string The name of the kubeconfig cluster to use
67
-h, --help help for cluster
8+
--kubeconfig string Path to the kubeconfig file to use for connecting to the cluster to be deleted, if empty, the default KUBECONFIG load path is used.
9+
-n, --namespace string If present, the namespace scope for this CLI request
710
-p, --provider-components string A yaml file containing cluster api provider controllers and supporting objects, if empty the value is loaded from the cluster's configuration store.
11+
--user string The name of the kubeconfig user to use
812

913
Global Flags:
1014
--alsologtostderr log to standard error as well as files

clusterctl/testdata/delete-cluster-no-args.golden

-19
This file was deleted.

gcp-deployer/deploy/deploy_helper.go

+1-5
Original file line numberDiff line numberDiff line change
@@ -258,11 +258,7 @@ func (d *deployer) copyKubeConfig(cluster *clusterv1.Cluster, master *clusterv1.
258258
}
259259

260260
func (d *deployer) initApiClient() error {
261-
c, err := clientcmd.NewClusterApiClientForDefaultSearchPath(d.configPath)
262-
if err != nil {
263-
return err
264-
}
265-
kubernetesClientSet, err := clientcmd.NewCoreClientSetForDefaultSearchPath(d.configPath)
261+
kubernetesClientSet, c, err := clientcmd.NewClientsForDefaultSearchpath(d.configPath, clientcmd.NewConfigOverrides())
266262
if err != nil {
267263
return err
268264
}

pkg/clientcmd/configutil.go

+23-21
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,16 @@ import (
2727
"sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset"
2828
)
2929

30+
// This is a convienience method to prevent the need of importing both this version of clientcmd and the client-go version
31+
func NewConfigOverrides() clientcmd.ConfigOverrides {
32+
return clientcmd.ConfigOverrides{}
33+
}
34+
3035
// NewCoreClientSetForDefaultSearchPath creates a core kubernetes clientset. If the kubeconfigPath is specified then the configuration is loaded from that path.
3136
// Otherwise the default kubeconfig search path is used.
32-
func NewCoreClientSetForDefaultSearchPath(kubeconfigPath string) (*kubernetes.Clientset, error) {
33-
config, err := newRestConfigForDefaultSearchPath(kubeconfigPath)
37+
// The overrides parameter is used to select a specific context of the config, for example, select the context with a given cluster name or namespace.
38+
func NewCoreClientSetForDefaultSearchPath(kubeconfigPath string, overrides clientcmd.ConfigOverrides) (*kubernetes.Clientset, error) {
39+
config, err := newRestConfigForDefaultSearchPath(kubeconfigPath, overrides)
3440
if err != nil {
3541
return nil, err
3642
}
@@ -48,8 +54,9 @@ func NewCoreClientSetForKubeconfig(kubeconfig string) (*kubernetes.Clientset, er
4854

4955
// NewClusterApiClientForDefaultSearchPath creates a Cluster API clientset. If the kubeconfigPath is specified then the configuration is loaded from that path.
5056
// Otherwise the default kubeconfig search path is used.
51-
func NewClusterApiClientForDefaultSearchPath(kubeconfigPath string) (*clientset.Clientset, error) {
52-
config, err := newRestConfigForDefaultSearchPath(kubeconfigPath)
57+
// The overrides parameter is used to select a specific context of the config, for example, select the context with a given cluster name or namespace.
58+
func NewClusterApiClientForDefaultSearchPath(kubeconfigPath string, overrides clientcmd.ConfigOverrides) (*clientset.Clientset, error) {
59+
config, err := newRestConfigForDefaultSearchPath(kubeconfigPath, overrides)
5360
if err != nil {
5461
return nil, err
5562
}
@@ -67,17 +74,9 @@ func NewClusterApiClientForKubeconfig(kubeconfig string) (*clientset.Clientset,
6774

6875
// NewClientsForDefaultSearchpath creates both a core kubernetes clientset and a cluster-api clientset. If the kubeconfigPath
6976
// is specified then the configuration is loaded from that path. Otherwise the default kubeconfig search path is used.
70-
func NewClientsForDefaultSearchpath(kubeconfigPath string) (*kubernetes.Clientset, *clientset.Clientset, error) {
71-
config, err := newRestConfigForDefaultSearchPath(kubeconfigPath)
72-
if err != nil {
73-
return nil, nil, err
74-
}
75-
return newClientsFromRestConfig(config)
76-
}
77-
78-
// NewClientsForKubeconfig creates both a core kubernetes clientset and a cluster-api clientset.
79-
func NewClientsForKubeconfig(kubeconfig string) (*kubernetes.Clientset, *clientset.Clientset, error) {
80-
config, err := newRestConfigForKubeconfig(kubeconfig)
77+
// The overrides parameter is used to select a specific context of the config, for example, select the context with a given cluster name or namespace.
78+
func NewClientsForDefaultSearchpath(kubeconfigPath string, overrides clientcmd.ConfigOverrides) (*kubernetes.Clientset, *clientset.Clientset, error) {
79+
config, err := newRestConfigForDefaultSearchPath(kubeconfigPath, overrides)
8180
if err != nil {
8281
return nil, nil, err
8382
}
@@ -98,14 +97,17 @@ func newClientsFromRestConfig(config *rest.Config) (*kubernetes.Clientset, *clie
9897
}
9998

10099
// newRestConfig creates a rest.Config for the given apiConfig
101-
func newRestConfig(apiConfig *api.Config) (*rest.Config, error) {
102-
return clientcmd.NewDefaultClientConfig(*apiConfig, &clientcmd.ConfigOverrides{}).ClientConfig()
100+
// The overrides parameter is used to select a specific context of the config, for example, select the context with a given cluster name or namespace.
101+
func newRestConfig(apiConfig *api.Config, overrides clientcmd.ConfigOverrides) (*rest.Config, error) {
102+
return clientcmd.NewDefaultClientConfig(*apiConfig, &overrides).ClientConfig()
103103
}
104104

105105
// newRestConfigForDefaultSearchPath creates a rest.Config by searching for the kubeconfig on the default search path. If an override 'kubeconfigPath' is
106106
// given then that path is used instead of the default path. If no override is given, an attempt is made to load the
107107
// 'in cluster' config. If this fails, then the default search path is used.
108-
func newRestConfigForDefaultSearchPath(kubeconfigPath string) (*rest.Config, error) {
108+
//
109+
// The overrides parameter is used to select a specific context of the config, for example, select the context with a given cluster name or namespace.
110+
func newRestConfigForDefaultSearchPath(kubeconfigPath string, overrides clientcmd.ConfigOverrides) (*rest.Config, error) {
109111
if kubeconfigPath == "" {
110112
config, err := rest.InClusterConfig()
111113
// if there is no err, continue because InClusterConfig is only expected to succeed if running inside of a pod.
@@ -117,16 +119,16 @@ func newRestConfigForDefaultSearchPath(kubeconfigPath string) (*rest.Config, err
117119
if err != nil {
118120
return nil, err
119121
}
120-
return newRestConfig(apiConfig)
122+
return newRestConfig(apiConfig, overrides)
121123
}
122124

123125
// newRestConfigForKubeconfig creates a rest.Config for a given kubeconfig string.
124126
func newRestConfigForKubeconfig(kubeconfig string) (*rest.Config, error) {
125-
apiConfig, err := newApiConfigForDefaultSearchPath(kubeconfig)
127+
apiConfig, err := newApiConfigForKubeconfig(kubeconfig)
126128
if err != nil {
127129
return nil, err
128130
}
129-
return newRestConfig(apiConfig)
131+
return newRestConfig(apiConfig, clientcmd.ConfigOverrides{})
130132
}
131133

132134
// newApiConfigForDefaultSearchPath creates an api.Config by searching for the kubeconfig on the default search path. If an override 'kubeconfigPath' is

tools/repair/util/repair.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func NewRepairer(dryRun bool, configPath string) (*repairer, error) {
3737
configPath = util.GetDefaultKubeConfigPath()
3838
}
3939

40-
c, err := clientcmd.NewClusterApiClientForDefaultSearchPath(configPath)
40+
c, err := clientcmd.NewClusterApiClientForDefaultSearchPath(configPath, clientcmd.NewConfigOverrides())
4141
if err != nil {
4242
return nil, err
4343
}

tools/upgrader/util/upgrade.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func initClient(kubeconfig string) error {
4141
if kubeconfig == "" {
4242
kubeconfig = util.GetDefaultKubeConfigPath()
4343
}
44-
coreClientset, clusterapiClientset, err := clientcmd.NewClientsForDefaultSearchpath(kubeconfig)
44+
coreClientset, clusterapiClientset, err := clientcmd.NewClientsForDefaultSearchpath(kubeconfig, clientcmd.NewConfigOverrides())
4545
if err != nil {
4646
glog.Fatalf("Error creating rest config: %v", err)
4747
return err

0 commit comments

Comments
 (0)