@@ -161,6 +161,16 @@ users:
161
161
# very large CA data, to this exec plugin as a part of the KUBERNETES_EXEC_INFO
162
162
# environment variable. Optional. Defaults to false.
163
163
provideClusterInfo : true
164
+
165
+ # The contract between the exec plugin and the standard input I/O stream. If the
166
+ # contract cannot be satisfied, this plugin will not be run and an error will be
167
+ # returned. Valid values are "Never" (this exec plugin never uses standard input),
168
+ # "IfAvailable" (this exec plugin wants to use standard input if it is available),
169
+ # or "Always" (this exec plugin requires standard input to function).
170
+ #
171
+ # In v1alpha1 and v1beta1, this is optional and defaults to IfAvailable. It is
172
+ # required otherwise.
173
+ interactiveMode : IfAvailable
164
174
clusters :
165
175
- name : my-cluster
166
176
cluster :
@@ -213,7 +223,39 @@ type ExecConfig struct {
213
223
// to false. Package k8s.io/client-go/tools/auth/exec provides helper methods for
214
224
// reading this environment variable.
215
225
ProvideClusterInfo bool `json:"provideClusterInfo"`
226
+
227
+ // InteractiveMode determines this plugin's relationship with standard input. Valid
228
+ // values are "Never" (this exec plugin never uses standard input), "IfAvailable" (this
229
+ // exec plugin wants to use standard input if it is available), or "Always" (this exec
230
+ // plugin requires standard input to function). See ExecInteractiveMode values for more
231
+ // details.
232
+ //
233
+ // If APIVersion is client.authentication.k8s.io/v1alpha1 or
234
+ // client.authentication.k8s.io/v1beta1, then this field is optional and defaults
235
+ // to "IfAvailable" when unset. Otherwise, this field is required.
236
+ // +optional
237
+ InteractiveMode ExecInteractiveMode `json:"interactiveMode,omitempty"`
216
238
}
239
+
240
+ // ExecInteractiveMode is a string that describes an exec plugin's relationship with standard input.
241
+ type ExecInteractiveMode string
242
+
243
+ const (
244
+ // NeverExecInteractiveMode declares that this exec plugin never needs to use standard
245
+ // input, and therefore the exec plugin will be run regardless of whether standard input is
246
+ // available for user input.
247
+ NeverExecInteractiveMode ExecInteractiveMode = "Never"
248
+ // IfAvailableExecInteractiveMode declares that this exec plugin would like to use standard input
249
+ // if it is available, but can still operate if standard input is not available. Therefore, the
250
+ // exec plugin will be run regardless of whether stdin is available for user input. If standard
251
+ // input is available for user input, then it will be provided to this exec plugin.
252
+ IfAvailableExecInteractiveMode ExecInteractiveMode = "IfAvailable"
253
+ // AlwaysExecInteractiveMode declares that this exec plugin requires standard input in order to
254
+ // run, and therefore the exec plugin will only be run if standard input is available for user
255
+ // input. If standard input is not available for user input, then the exec plugin will not be run
256
+ // and an error will be returned by the exec plugin runner.
257
+ AlwaysExecInteractiveMode ExecInteractiveMode = "Always"
258
+ )
217
259
```
218
260
219
261
` apiVersion ` specifies the expected version of this API that the plugin
@@ -234,6 +276,14 @@ is missing.
234
276
potentially contain very large CA data, to this exec plugin as a part
235
277
of the ` KUBERNETES_EXEC_INFO ` environment variable.
236
278
279
+ ` interactiveMode ` specifies the contract between the exec plugin and the
280
+ standard input I/O stream. If the contract cannot be satisfied, this plugin will
281
+ not be run and an error will be returned. Valid values are "Never" (this exec
282
+ plugin never uses standard input), "IfAvailable" (this exec plugin wants to use
283
+ standard input if it is available), or "Always" (this exec plugin requires
284
+ standard input to function). In v1alpha1 and v1beta1, this is optional and
285
+ defaults to IfAvailable. It is required otherwise.
286
+
237
287
### Provider input format
238
288
239
289
In JSON:
@@ -243,6 +293,7 @@ In JSON:
243
293
"apiVersion" : " client.authentication.k8s.io/v1beta1" ,
244
294
"kind" : " ExecCredential" ,
245
295
"spec" : {
296
+ "interactive" : true ,
246
297
"cluster" : {
247
298
"server" : " https://1.2.3.4:8080" ,
248
299
"tls-server-name" : " bar" ,
@@ -281,6 +332,9 @@ type ExecCredentialSpec struct {
281
332
// ExecConfig.ProvideClusterInfo).
282
333
// +optional
283
334
Cluster *Cluster ` json:"cluster,omitempty"`
335
+
336
+ // Interactive declares whether stdin has been passed to this exec plugin.
337
+ Interactive bool ` json:"interactive"`
284
338
}
285
339
286
340
// Cluster contains information to allow an exec plugin to communicate with the
@@ -437,6 +491,11 @@ func LoadExecCredentialFromEnv() (runtime.Object, *rest.Config, error)
437
491
func LoadExecCredential(data []byte) (runtime.Object, *rest.Config, error)
438
492
```
439
493
494
+ The `interactive` field is used to communicate to the exec plugin whether
495
+ standard input is available for use. This is helpful for plugins that can
496
+ operate with and without standard input so that they can easily distinguish
497
+ between the two cases.
498
+
440
499
### Provider output format
441
500
442
501
In JSON:
@@ -550,9 +609,12 @@ var (
550
609
execPluginCalls = k8smetrics.NewCounterVec (
551
610
&k8smetrics.CounterOpts {
552
611
Name : " rest_client_exec_plugin_call_total" ,
553
- Help : " Number of calls to an exec plugin, partitioned by exit code." ,
612
+ Help : " Number of calls to an exec plugin, partitioned by the type of " +
613
+ " event encountered (no_error, plugin_execution_error, plugin_not_found_error, " +
614
+ " client_internal_error) and an optional exit code. The exit code will " +
615
+ " be set to 0 if and only if the plugin call was successful." ,
554
616
},
555
- []string {" code" },
617
+ []string {" code" , " call_status " },
556
618
)
557
619
)
558
620
```
@@ -572,8 +634,8 @@ type ExpiryMetric interface {
572
634
573
635
// CallsMetric counts calls that take place for a specific exec plugin.
574
636
type CallsMetric interface {
575
- // Increment increments a counter per exitCode.
576
- Increment (exitCode int )
637
+ // Increment increments a counter per exitCode and callStatus .
638
+ Increment (exitCode int , callStatus string )
577
639
}
578
640
579
641
var (
@@ -582,13 +644,13 @@ var (
582
644
// ClientCertRotationAge is the age of a certificate that has just been rotated.
583
645
ClientCertRotationAge DurationMetric = noopDuration{}
584
646
// ExecPluginCalls is the number of calls made to an exec plugin, partitioned by
585
- // exit code.
647
+ // exit code and call status .
586
648
ExecPluginCalls CallsMetric = noopCalls{}
587
649
)
588
650
```
589
651
590
- The ` "code" ` label of these metrics is an attempt to elucidate the exec plugin
591
- failure mode to the user.
652
+ The ` "code" ` and ` "call_status" ` labels of these metrics are an attempt to
653
+ elucidate the exec plugin failure mode to the user.
592
654
593
655
### Risks and Mitigations
594
656
@@ -644,6 +706,8 @@ Integration (or e2e CLI) tests to confirm:
644
706
+ Cert based auth
645
707
- Interactive login flows work
646
708
+ TTY forwarding between client and executable works
709
+ + ` kubectl ` commands and exec credential plugins do not fight for standard input
710
+ + All ` InteractiveMode ` values are supported
647
711
- Metrics are reported as they should
648
712
649
713
### Graduation Criteria
0 commit comments