@@ -11,12 +11,15 @@ import (
1111 "testing"
1212
1313 "github.com/MakeNowJust/heredoc"
14+ "github.com/google/go-cmp/cmp"
1415
1516 kapierrs "k8s.io/apimachinery/pkg/api/errors"
17+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1618 "k8s.io/cli-runtime/pkg/genericiooptions"
1719 restclient "k8s.io/client-go/rest"
1820 kclientcmdapi "k8s.io/client-go/tools/clientcmd/api"
1921
22+ userv1 "github.com/openshift/api/user/v1"
2023 "github.com/openshift/library-go/pkg/oauth/oauthdiscovery"
2124 cliconfig "github.com/openshift/oc/pkg/helpers/kubeconfig"
2225)
@@ -374,6 +377,114 @@ func TestDialToHTTPSServer(t *testing.T) {
374377 }
375378}
376379
380+ func TestPreserveExecProviderOnUsernameLogin (t * testing.T ) {
381+ // Test that when using -u flag with existing OIDC credentials,
382+ // the ExecProvider configuration is preserved
383+
384+ execProvider := & kclientcmdapi.ExecConfig {
385+ APIVersion : "client.authentication.k8s.io/v1" ,
386+ Command : "oc" ,
387+ Args : []string {
388+ "get-token" ,
389+ "--issuer-url=https://oauth.example.com" ,
390+ "--client-id=test-client" ,
391+ "--callback-address=127.0.0.1:8080" ,
392+ },
393+ InstallHint : "Please be sure that oc is defined in $PATH to be executed as credentials exec plugin" ,
394+ InteractiveMode : kclientcmdapi .IfAvailableExecInteractiveMode ,
395+ }
396+
397+ testCases := map [string ]struct {
398+ username string
399+ existingExecProvider * kclientcmdapi.ExecConfig
400+ expectedExecProvider * kclientcmdapi.ExecConfig
401+ }{
402+ "preserve OIDC exec provider" : {
403+ username :
"oidc-user-test:[email protected] " ,
404+ existingExecProvider : execProvider ,
405+ expectedExecProvider : execProvider ,
406+ },
407+ "no exec provider preserved when none exists" : {
408+ username : "regular-user" ,
409+ existingExecProvider : nil ,
410+ expectedExecProvider : nil ,
411+ },
412+ }
413+
414+ for name , test := range testCases {
415+ t .Run (name , func (t * testing.T ) {
416+ // Mock config constants.
417+ serverURL := "https://api.test.devcluster.openshift.com:6443"
418+ clusterNick := "api-test-devcluster-openshift-com:6443"
419+ userNick := test .username + "/" + clusterNick
420+ contextNick := "default/" + clusterNick + "/" + test .username
421+
422+ // Create starting kubeconfig with existing OIDC credentials.
423+ startingConfig := & kclientcmdapi.Config {
424+ Clusters : map [string ]* kclientcmdapi.Cluster {
425+ clusterNick : {
426+ Server : serverURL ,
427+ },
428+ },
429+ AuthInfos : map [string ]* kclientcmdapi.AuthInfo {
430+ userNick : {
431+ Exec : test .existingExecProvider ,
432+ },
433+ },
434+ Contexts : map [string ]* kclientcmdapi.Context {
435+ contextNick : {
436+ Cluster : clusterNick ,
437+ AuthInfo : userNick ,
438+ Namespace : "default" ,
439+ },
440+ },
441+ CurrentContext : contextNick ,
442+ }
443+
444+ // Setup LoginOptions with username and existing config
445+ options := & LoginOptions {
446+ Username : test .username ,
447+ Server : serverURL ,
448+ StartingKubeConfig : startingConfig ,
449+ Config : & restclient.Config {
450+ Host : serverURL ,
451+ ExecProvider : test .existingExecProvider ,
452+ },
453+ IOStreams : genericiooptions .NewTestIOStreamsDiscard (),
454+ }
455+
456+ // Mock the WhoAmI function to always match the user.
457+ whoAmICalled := false
458+ options .whoAmIFunc = func (clientConfig * restclient.Config ) (* userv1.User , error ) {
459+ whoAmICalled = true
460+ return & userv1.User {
461+ ObjectMeta : metav1.ObjectMeta {
462+ Name : test .username ,
463+ },
464+ }, nil
465+ }
466+
467+ // Calling gatherAuthInfo should preserve ExecProvider.
468+ if err := options .gatherAuthInfo (); err != nil {
469+ t .Fatalf ("gatherAuthInfo failed: %v" , err )
470+ }
471+
472+ // Verify ExecProvider is preserved correctly.
473+ if options .Config == nil {
474+ t .Fatal ("LoginOptions.Config is nil" )
475+ }
476+ if ! cmp .Equal (options .Config .ExecProvider , test .expectedExecProvider ) {
477+ t .Errorf ("expected provider mismatch: \n %s\n " , cmp .Diff (test .expectedExecProvider , options .Config .ExecProvider ))
478+ }
479+
480+ // Just check additionally that whoAmI has been called.
481+ if ! whoAmICalled {
482+ t .Errorf ("WhoAmI function has not been called" )
483+ }
484+ })
485+ }
486+ }
487+
377488func newTLSServer (certString , keyString string ) (* httptest.Server , error ) {
378489 invoked := make (chan struct {}, 1 )
379490 server := httptest .NewUnstartedServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
0 commit comments