Merge pull request #108810 from enj/enj/i/create_token_duration

kubectl create token: use duration instead of expiration seconds
This commit is contained in:
Kubernetes Prow Robot 2022-03-18 16:05:56 -07:00 committed by GitHub
commit b383035ca3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 25 deletions

View File

@ -20,6 +20,7 @@ import (
"context"
"fmt"
"strings"
"time"
"github.com/spf13/cobra"
@ -35,6 +36,7 @@ import (
"k8s.io/kubectl/pkg/util"
"k8s.io/kubectl/pkg/util/templates"
"k8s.io/kubectl/pkg/util/term"
"k8s.io/utils/pointer"
)
// TokenOptions is the data required to perform a token request operation.
@ -57,8 +59,8 @@ type TokenOptions struct {
// Audiences indicate the valid audiences for the requested token. If unset, defaults to the Kubernetes API server audiences.
Audiences []string
// ExpirationSeconds is the requested token lifetime. Optional.
ExpirationSeconds int64
// Duration is the requested token lifetime. Optional.
Duration time.Duration
// CoreClient is the API client used to request the token. Required.
CoreClient corev1client.CoreV1Interface
@ -78,7 +80,7 @@ var (
kubectl create token myapp --namespace myns
# Request a token with a custom expiration
kubectl create token myapp --expiration-seconds 600
kubectl create token myapp --duration 10m
# Request a token with a custom audience
kubectl create token myapp --audience https://example.com
@ -134,7 +136,7 @@ func NewCmdCreateToken(f cmdutil.Factory, ioStreams genericclioptions.IOStreams)
cmd.Flags().StringArrayVar(&o.Audiences, "audience", o.Audiences, "Audience of the requested token. If unset, defaults to requesting a token for use with the Kubernetes API server. May be repeated to request a token valid for multiple audiences.")
cmd.Flags().Int64Var(&o.ExpirationSeconds, "expiration-seconds", o.ExpirationSeconds, "Requested lifetime of the issued token. The server may return a token with a longer or shorter lifetime.")
cmd.Flags().DurationVar(&o.Duration, "duration", o.Duration, "Requested lifetime of the issued token. The server may return a token with a longer or shorter lifetime.")
cmd.Flags().StringVar(&o.BoundObjectKind, "bound-object-kind", o.BoundObjectKind, "Kind of an object to bind the token to. "+
"Supported kinds are "+strings.Join(sets.StringKeySet(boundObjectKindToAPIVersion).List(), ", ")+". "+
@ -192,8 +194,11 @@ func (o *TokenOptions) Validate() error {
if len(o.Namespace) == 0 {
return fmt.Errorf("--namespace is required")
}
if o.ExpirationSeconds < 0 {
return fmt.Errorf("--expiration-seconds must be positive")
if o.Duration < 0 {
return fmt.Errorf("--duration must be positive")
}
if o.Duration%time.Second != 0 {
return fmt.Errorf("--duration cannot be expressed in units less than seconds")
}
for _, aud := range o.Audiences {
if len(aud) == 0 {
@ -227,8 +232,8 @@ func (o *TokenOptions) Run() error {
Audiences: o.Audiences,
},
}
if o.ExpirationSeconds > 0 {
request.Spec.ExpirationSeconds = &o.ExpirationSeconds
if o.Duration > 0 {
request.Spec.ExpirationSeconds = pointer.Int64(int64(o.Duration / time.Second))
}
if len(o.BoundObjectKind) > 0 {
request.Spec.BoundObjectRef = &authenticationv1.BoundObjectReference{

View File

@ -22,8 +22,8 @@ import (
"io/ioutil"
"net/http"
"reflect"
"strconv"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"k8s.io/utils/pointer"
@ -44,14 +44,14 @@ func TestCreateToken(t *testing.T) {
tests := []struct {
test string
name string
namespace string
output string
boundObjectKind string
boundObjectName string
boundObjectUID string
audiences []string
expirationSeconds int
name string
namespace string
output string
boundObjectKind string
boundObjectName string
boundObjectUID string
audiences []string
duration time.Duration
serverResponseToken string
serverResponseError string
@ -183,16 +183,22 @@ status:
},
{
test: "invalid expiration",
name: "mysa",
expirationSeconds: -1,
expectStderr: `error: --expiration-seconds must be positive`,
test: "invalid duration",
name: "mysa",
duration: -1,
expectStderr: `error: --duration must be positive`,
},
{
test: "valid expiration",
test: "invalid duration unit",
name: "mysa",
duration: time.Microsecond,
expectStderr: `error: --duration cannot be expressed in units less than seconds`,
},
{
test: "valid duration",
name: "mysa",
expirationSeconds: 1000,
duration: 1000 * time.Second,
expectRequestPath: "/api/v1/namespaces/test/serviceaccounts/mysa/token",
expectTokenRequest: &authenticationv1.TokenRequest{
@ -310,8 +316,8 @@ status:
for _, aud := range test.audiences {
cmd.Flags().Set("audience", aud)
}
if test.expirationSeconds != 0 {
cmd.Flags().Set("expiration-seconds", strconv.Itoa(test.expirationSeconds))
if test.duration != 0 {
cmd.Flags().Set("duration", test.duration.String())
}
cmd.Run(cmd, []string{test.name})