@@ -28,13 +28,15 @@ import (
28
28
"github.com/lithammer/dedent"
29
29
"github.com/pkg/errors"
30
30
"github.com/spf13/cobra"
31
+ flag "github.com/spf13/pflag"
31
32
"k8s.io/apimachinery/pkg/util/sets"
32
33
clientset "k8s.io/client-go/kubernetes"
33
34
"k8s.io/klog"
34
35
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
35
36
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
36
37
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
37
38
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
39
+ "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
38
40
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
39
41
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
40
42
etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd"
@@ -48,99 +50,197 @@ import (
48
50
utilsexec "k8s.io/utils/exec"
49
51
)
50
52
51
- // NewCmdReset returns the "kubeadm reset" command
52
- func NewCmdReset (in io.Reader , out io.Writer ) * cobra.Command {
53
- var certsDir string
53
+ // resetOptions defines all the options exposed via flags by kubeadm reset.
54
+ type resetOptions struct {
55
+ certificatesDir string
56
+ criSocketPath string
57
+ forceReset bool
58
+ ignorePreflightErrors []string
59
+ kubeconfigPath string
60
+ }
61
+
62
+ // resetData defines all the runtime information used when running the kubeadm reset worklow;
63
+ // this data is shared across all the phases that are included in the workflow.
64
+ type resetData struct {
65
+ certificatesDir string
66
+ client clientset.Interface
67
+ criSocketPath string
68
+ forceReset bool
69
+ ignorePreflightErrors sets.String
70
+ inputReader io.Reader
71
+ outputWriter io.Writer
72
+ cfg * kubeadmapi.InitConfiguration
73
+ }
74
+
75
+ // newResetOptions returns a struct ready for being used for creating cmd join flags.
76
+ func newResetOptions () * resetOptions {
77
+ return & resetOptions {
78
+ certificatesDir : kubeadmapiv1beta2 .DefaultCertificatesDir ,
79
+ forceReset : false ,
80
+ kubeconfigPath : kubeadmconstants .GetAdminKubeConfigPath (),
81
+ }
82
+ }
83
+
84
+ // newResetData returns a new resetData struct to be used for the execution of the kubeadm reset workflow.
85
+ func newResetData (cmd * cobra.Command , options * resetOptions , in io.Reader , out io.Writer ) (* resetData , error ) {
86
+ var cfg * kubeadmapi.InitConfiguration
87
+ ignorePreflightErrorsSet , err := validation .ValidateIgnorePreflightErrors (options .ignorePreflightErrors )
88
+ if err != nil {
89
+ return nil , err
90
+ }
91
+
92
+ client , err := getClientset (options .kubeconfigPath , false )
93
+ if err == nil {
94
+ klog .V (1 ).Infof ("[reset] Loaded client set from kubeconfig file: %s" , options .kubeconfigPath )
95
+ cfg , err = configutil .FetchInitConfigurationFromCluster (client , out , "reset" , false )
96
+ if err != nil {
97
+ klog .Warningf ("[reset] Unable to fetch the kubeadm-config ConfigMap from cluster: %v" , err )
98
+ }
99
+ } else {
100
+ klog .V (1 ).Infof ("[reset] Could not obtain a client set from the kubeconfig file: %s" , options .kubeconfigPath )
101
+ }
102
+
54
103
var criSocketPath string
55
- var ignorePreflightErrors []string
56
- var forceReset bool
57
- var client clientset.Interface
58
- kubeConfigFile := kubeadmconstants .GetAdminKubeConfigPath ()
104
+ if options .criSocketPath == "" {
105
+ criSocketPath , err = resetDetectCRISocket (cfg )
106
+ if err != nil {
107
+ return nil , err
108
+ }
109
+ klog .V (1 ).Infof ("[reset] Detected and using CRI socket: %s" , criSocketPath )
110
+ }
111
+
112
+ return & resetData {
113
+ certificatesDir : options .certificatesDir ,
114
+ client : client ,
115
+ criSocketPath : criSocketPath ,
116
+ forceReset : options .forceReset ,
117
+ ignorePreflightErrors : ignorePreflightErrorsSet ,
118
+ inputReader : in ,
119
+ outputWriter : out ,
120
+ cfg : cfg ,
121
+ }, nil
122
+ }
123
+
124
+ // AddResetFlags adds reset flags
125
+ func AddResetFlags (flagSet * flag.FlagSet , resetOptions * resetOptions ) {
126
+ flagSet .StringVar (
127
+ & resetOptions .certificatesDir , options .CertificatesDir , resetOptions .certificatesDir ,
128
+ `The path to the directory where the certificates are stored. If specified, clean this directory.` ,
129
+ )
130
+ flagSet .BoolVarP (
131
+ & resetOptions .forceReset , options .ForceReset , "f" , false ,
132
+ "Reset the node without prompting for confirmation." ,
133
+ )
134
+
135
+ options .AddKubeConfigFlag (flagSet , & resetOptions .kubeconfigPath )
136
+ options .AddIgnorePreflightErrorsFlag (flagSet , & resetOptions .ignorePreflightErrors )
137
+ cmdutil .AddCRISocketFlag (flagSet , & resetOptions .criSocketPath )
138
+ }
139
+
140
+ // NewCmdReset returns the "kubeadm reset" command
141
+ func NewCmdReset (in io.Reader , out io.Writer , resetOptions * resetOptions ) * cobra.Command {
142
+ if resetOptions == nil {
143
+ resetOptions = newResetOptions ()
144
+ }
145
+ resetRunner := workflow .NewRunner ()
59
146
60
147
cmd := & cobra.Command {
61
148
Use : "reset" ,
62
149
Short : "Run this to revert any changes made to this host by 'kubeadm init' or 'kubeadm join'" ,
63
150
Run : func (cmd * cobra.Command , args []string ) {
64
- ignorePreflightErrorsSet , err := validation . ValidateIgnorePreflightErrors ( ignorePreflightErrors )
151
+ c , err := resetRunner . InitData ( args )
65
152
kubeadmutil .CheckErr (err )
66
153
67
- var cfg * kubeadmapi.InitConfiguration
68
- client , err = getClientset (kubeConfigFile , false )
69
- if err == nil {
70
- klog .V (1 ).Infof ("[reset] Loaded client set from kubeconfig file: %s" , kubeConfigFile )
71
- cfg , err = configutil .FetchInitConfigurationFromCluster (client , os .Stdout , "reset" , false )
72
- if err != nil {
73
- klog .Warningf ("[reset] Unable to fetch the kubeadm-config ConfigMap from cluster: %v" , err )
74
- }
75
- } else {
76
- klog .V (1 ).Infof ("[reset] Could not obtain a client set from the kubeconfig file: %s" , kubeConfigFile )
77
- }
78
-
79
- if criSocketPath == "" {
80
- criSocketPath , err = resetDetectCRISocket (cfg )
81
- kubeadmutil .CheckErr (err )
82
- klog .V (1 ).Infof ("[reset] Detected and using CRI socket: %s" , criSocketPath )
83
- }
84
-
85
- r , err := NewReset (in , ignorePreflightErrorsSet , forceReset , certsDir , criSocketPath )
154
+ err = resetRunner .Run (args )
86
155
kubeadmutil .CheckErr (err )
87
- kubeadmutil .CheckErr (r .Run (out , client , cfg ))
156
+ // TODO: remove this once we have all phases in place.
157
+ // the method joinData.Run() itself should be removed too.
158
+ data := c .(* resetData )
159
+ kubeadmutil .CheckErr (data .Run ())
88
160
},
89
161
}
90
162
91
- options .AddIgnorePreflightErrorsFlag (cmd .PersistentFlags (), & ignorePreflightErrors )
92
- options .AddKubeConfigFlag (cmd .PersistentFlags (), & kubeConfigFile )
163
+ AddResetFlags (cmd .Flags (), resetOptions )
93
164
94
- cmd .PersistentFlags ().StringVar (
95
- & certsDir , "cert-dir" , kubeadmapiv1beta2 .DefaultCertificatesDir ,
96
- "The path to the directory where the certificates are stored. If specified, clean this directory." ,
97
- )
165
+ // initialize the workflow runner with the list of phases
166
+ // TODO: append phases here
98
167
99
- cmdutil .AddCRISocketFlag (cmd .PersistentFlags (), & criSocketPath )
168
+ // sets the data builder function, that will be used by the runner
169
+ // both when running the entire workflow or single phases
170
+ resetRunner .SetDataInitializer (func (cmd * cobra.Command , args []string ) (workflow.RunData , error ) {
171
+ return newResetData (cmd , resetOptions , in , out )
172
+ })
100
173
101
- cmd .PersistentFlags ().BoolVarP (
102
- & forceReset , "force" , "f" , false ,
103
- "Reset the node without prompting for confirmation." ,
104
- )
174
+ // binds the Runner to kubeadm init command by altering
175
+ // command help, adding --skip-phases flag and by adding phases subcommands
176
+ resetRunner .BindToCommand (cmd )
105
177
106
178
return cmd
107
179
}
108
180
109
- // Reset defines struct used for kubeadm reset command
110
- type Reset struct {
111
- certsDir string
112
- criSocketPath string
181
+ // Cfg returns the InitConfiguration.
182
+ func (r * resetData ) Cfg () * kubeadmapi.InitConfiguration {
183
+ return r .cfg
184
+ }
185
+
186
+ // CertificatesDir returns the CertificatesDir.
187
+ func (r * resetData ) CertificatesDir () string {
188
+ return r .certificatesDir
189
+ }
190
+
191
+ // Client returns the Client for accessing the cluster.
192
+ func (r * resetData ) Client () clientset.Interface {
193
+ return r .client
194
+ }
195
+
196
+ // ForceReset returns the forceReset flag.
197
+ func (r * resetData ) ForceReset () bool {
198
+ return r .forceReset
113
199
}
114
200
115
- // NewReset instantiate Reset struct
116
- func NewReset (in io.Reader , ignorePreflightErrors sets.String , forceReset bool , certsDir , criSocketPath string ) (* Reset , error ) {
117
- if ! forceReset {
201
+ // InputReader returns the io.reader used to read messages.
202
+ func (r * resetData ) InputReader () io.Reader {
203
+ return r .inputReader
204
+ }
205
+
206
+ // IgnorePreflightErrors returns the list of preflight errors to ignore.
207
+ func (r * resetData ) IgnorePreflightErrors () sets.String {
208
+ return r .ignorePreflightErrors
209
+ }
210
+
211
+ func (r * resetData ) preflight () error {
212
+ if ! r .ForceReset () {
118
213
fmt .Println ("[reset] WARNING: Changes made to this host by 'kubeadm init' or 'kubeadm join' will be reverted." )
119
214
fmt .Print ("[reset] Are you sure you want to proceed? [y/N]: " )
120
- s := bufio .NewScanner (in )
215
+ s := bufio .NewScanner (r . InputReader () )
121
216
s .Scan ()
122
217
if err := s .Err (); err != nil {
123
- return nil , err
218
+ return err
124
219
}
125
220
if strings .ToLower (s .Text ()) != "y" {
126
- return nil , errors .New ("Aborted reset operation" )
221
+ return errors .New ("Aborted reset operation" )
127
222
}
128
223
}
129
224
130
225
fmt .Println ("[preflight] Running pre-flight checks" )
131
- if err := preflight .RunRootCheckOnly (ignorePreflightErrors ); err != nil {
132
- return nil , err
226
+ if err := preflight .RunRootCheckOnly (r . IgnorePreflightErrors () ); err != nil {
227
+ return err
133
228
}
134
229
135
- return & Reset {
136
- certsDir : certsDir ,
137
- criSocketPath : criSocketPath ,
138
- }, nil
230
+ return nil
139
231
}
140
232
141
233
// Run reverts any changes made to this host by "kubeadm init" or "kubeadm join".
142
- func (r * Reset ) Run (out io. Writer , client clientset. Interface , cfg * kubeadmapi. InitConfiguration ) error {
234
+ func (r * resetData ) Run () error {
143
235
var dirsToClean []string
236
+ cfg := r .Cfg ()
237
+ certsDir := r .CertificatesDir ()
238
+ client := r .Client ()
239
+
240
+ err := r .preflight ()
241
+ if err != nil {
242
+ return err
243
+ }
144
244
145
245
// Reset the ClusterStatus for a given control-plane node.
146
246
if isControlPlane () && cfg != nil {
@@ -203,10 +303,10 @@ func (r *Reset) Run(out io.Writer, client clientset.Interface, cfg *kubeadmapi.I
203
303
204
304
// Remove contents from the config and pki directories
205
305
klog .V (1 ).Infoln ("[reset] Removing contents from the config and pki directories" )
206
- if r . certsDir != kubeadmapiv1beta2 .DefaultCertificatesDir {
207
- klog .Warningf ("[reset] WARNING: Cleaning a non-default certificates directory: %q\n " , r . certsDir )
306
+ if certsDir != kubeadmapiv1beta2 .DefaultCertificatesDir {
307
+ klog .Warningf ("[reset] WARNING: Cleaning a non-default certificates directory: %q\n " , certsDir )
208
308
}
209
- resetConfigDir (kubeadmconstants .KubernetesDir , r . certsDir )
309
+ resetConfigDir (kubeadmconstants .KubernetesDir , certsDir )
210
310
211
311
// Output help text instructing user how to remove iptables rules
212
312
msg := dedent .Dedent (`
0 commit comments