Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions cmd/common/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"io"

ocmsdk "github.com/openshift-online/ocm-sdk-go"
bplogin "github.com/openshift/backplane-cli/cmd/ocm-backplane/login"
bpconfig "github.com/openshift/backplane-cli/pkg/cli/config"
"github.com/openshift/osdctl/pkg/utils"
Expand Down Expand Up @@ -76,3 +77,31 @@ func GetKubeConfigAndClient(clusterID string, elevationReasons ...string) (clien
}
return kubeCli, kubeconfig, clientset, err
}

// If some elevationReasons are provided, then the config will be elevated with user backplane-cluster-admin
// Using provided OCM sdk connection for config values.
func GetKubeConfigAndClientWithConn(clusterID string, ocm *ocmsdk.Connection, elevationReasons ...string) (client.Client, *rest.Config, *kubernetes.Clientset, error) {
bp, err := bpconfig.GetBackplaneConfigurationWithConn(ocm)
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to load backplane-cli config: %w", err)
}
var kubeconfig *rest.Config
if len(elevationReasons) == 0 {
kubeconfig, err = bplogin.GetRestConfigWithConn(bp, ocm, clusterID)
} else {
kubeconfig, err = bplogin.GetRestConfigAsUserWithConn(bp, ocm, clusterID, "backplane-cluster-admin", elevationReasons...)
}
if err != nil {
return nil, nil, nil, err
}
// create the clientset
clientset, err := kubernetes.NewForConfig(kubeconfig)
if err != nil {
return nil, nil, nil, err
}
kubeCli, err := client.New(kubeconfig, client.Options{})
if err != nil {
return nil, nil, nil, err
}
return kubeCli, kubeconfig, clientset, nil
}
70 changes: 70 additions & 0 deletions cmd/common/helpers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package common

import (
"testing"

sdk "github.com/openshift-online/ocm-sdk-go"
)

// TestGetKubeConfigAndClientWithConn tests the GetKubeConfigAndClientWithConn function
// which creates a Kubernetes client, REST config, and clientset using a provided OCM SDK
// connection. This function supports both regular and elevated (backplane-cluster-admin)
// access based on the presence of elevation reasons.
func TestGetKubeConfigAndClientWithConn(t *testing.T) {
tests := []struct {
name string
clusterID string
ocmConn *sdk.Connection
elevationReasons []string
wantErr bool
}{
{
// Test that passing a nil OCM connection without elevation returns an error
name: "nil OCM connection",
clusterID: "test-cluster-id",
ocmConn: nil,
elevationReasons: nil,
wantErr: true,
},
{
// Test that passing a nil OCM connection with elevation reasons also returns an error
name: "nil OCM connection with elevation reasons",
clusterID: "test-cluster-id",
ocmConn: nil,
elevationReasons: []string{"testing"},
wantErr: true,
},
{
// Test that passing an empty cluster ID with nil connection returns an error
name: "empty cluster ID with nil connection",
clusterID: "",
ocmConn: nil,
elevationReasons: nil,
wantErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
kubeCli, kubeconfig, clientset, err := GetKubeConfigAndClientWithConn(tt.clusterID, tt.ocmConn, tt.elevationReasons...)
if tt.wantErr {
if err == nil {
t.Errorf("GetKubeConfigAndClientWithConn() expected error but got none")
}
} else {
if err != nil {
t.Errorf("GetKubeConfigAndClientWithConn() unexpected error = %v", err)
}
if kubeCli == nil {
t.Errorf("GetKubeConfigAndClientWithConn() returned nil kubeCli")
}
if kubeconfig == nil {
t.Errorf("GetKubeConfigAndClientWithConn() returned nil kubeconfig")
}
if clientset == nil {
t.Errorf("GetKubeConfigAndClientWithConn() returned nil clientset")
}
}
})
}
}
1 change: 1 addition & 0 deletions cmd/hive/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package hive

import (
"fmt"

cd "github.com/openshift/osdctl/cmd/hive/clusterdeployment"
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
Expand Down
43 changes: 42 additions & 1 deletion pkg/k8s/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"io"

sdk "github.com/openshift-online/ocm-sdk-go"
bplogin "github.com/openshift/backplane-cli/cmd/ocm-backplane/login"
bpconfig "github.com/openshift/backplane-cli/pkg/cli/config"
bputils "github.com/openshift/backplane-cli/pkg/utils"
Expand Down Expand Up @@ -162,10 +163,30 @@ func NewRestConfig(clusterID string) (*rest.Config, error) {
return cfg, nil
}

// Create Backplane connection to a provided cluster, using a provided ocm sdk connection
// This is intended to allow backplane connections to multiple clusters which exist in different
// ocm environments by allowing the caller to provide an ocm connection to the function.
func NewWithConn(clusterID string, options client.Options, ocmConn *sdk.Connection) (client.Client, error) {
if ocmConn == nil {
return nil, fmt.Errorf("nil OCM sdk connection provided to NewWithConn()")
}
bp, err := bpconfig.GetBackplaneConfigurationWithConn(ocmConn)
if err != nil {
return nil, fmt.Errorf("failed to load backplane-cli config: %w", err)
}

cfg, err := bplogin.GetRestConfigWithConn(bp, ocmConn, clusterID)
if err != nil {
return nil, err
}
setRuntimeLoggerDiscard()
return client.New(cfg, options)
}

func NewAsBackplaneClusterAdmin(clusterID string, options client.Options, elevationReasons ...string) (client.Client, error) {
bp, err := bpconfig.GetBackplaneConfiguration()
if err != nil {
return nil, fmt.Errorf("failed to load backplane-cli config: %v", err)
return nil, fmt.Errorf("failed to load backplane-cli config: %w", err)
}

cfg, err := bplogin.GetRestConfigAsUser(bp, clusterID, "backplane-cluster-admin", elevationReasons...)
Expand All @@ -176,6 +197,26 @@ func NewAsBackplaneClusterAdmin(clusterID string, options client.Options, elevat
return client.New(cfg, options)
}

// Create Backplane connection as cluster admin to a provided cluster, using a provided ocm sdk connection
// This is intended to allow backplane connections to multiple clusters which exist in different
// ocm environments by allowing the caller to provide an ocm connection to the function.
func NewAsBackplaneClusterAdminWithConn(clusterID string, options client.Options, ocmConn *sdk.Connection, elevationReasons ...string) (client.Client, error) {
if ocmConn == nil {
return nil, fmt.Errorf("nil OCM sdk connection provided to NewAsBackplaneClusterAdminWithConn()")
}
bp, err := bpconfig.GetBackplaneConfigurationWithConn(ocmConn)
if err != nil {
return nil, fmt.Errorf("failed to load backplane-cli config: %w", err)
}

cfg, err := bplogin.GetRestConfigAsUserWithConn(bp, ocmConn, clusterID, "backplane-cluster-admin", elevationReasons...)
if err != nil {
return nil, err
}
setRuntimeLoggerDiscard()
return client.New(cfg, options)
}

func setRuntimeLoggerDiscard() {
// To avoid warnings/backtrace, if k8s controller-runtime logger has not already been set, do it now...
if !log.Log.Enabled() {
Expand Down
117 changes: 117 additions & 0 deletions pkg/k8s/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package k8s

import (
"testing"

sdk "github.com/openshift-online/ocm-sdk-go"
"sigs.k8s.io/controller-runtime/pkg/client"
)

// TestNewWithConn tests the NewWithConn function which creates a Kubernetes client
// using backplane with a provided OCM SDK connection. This allows connecting to clusters
// in different OCM environments by providing a custom OCM connection.
func TestNewWithConn(t *testing.T) {
tests := []struct {
name string
clusterID string
options client.Options
ocmConn *sdk.Connection
wantErr bool
}{
{
// Test that passing a nil OCM connection returns an error
name: "nil OCM connection",
clusterID: "test-cluster-id",
options: client.Options{},
ocmConn: nil,
wantErr: true,
},
{
// Test that passing an empty cluster ID with nil connection returns an error
name: "empty cluster ID with nil connection",
clusterID: "",
options: client.Options{},
ocmConn: nil,
wantErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
client, err := NewWithConn(tt.clusterID, tt.options, tt.ocmConn)
if tt.wantErr {
if err == nil {
t.Errorf("NewWithConn() expected error but got none")
}
} else {
if err != nil {
t.Errorf("NewWithConn() unexpected error = %v", err)
}
if client == nil {
t.Errorf("NewWithConn() returned nil client")
}
}
})
}
}

// TestNewAsBackplaneClusterAdminWithConn tests the NewAsBackplaneClusterAdminWithConn function
// which creates an elevated Kubernetes client (backplane-cluster-admin) using a provided OCM
// SDK connection. This function allows connecting to clusters in different OCM environments
// with elevated permissions.
func TestNewAsBackplaneClusterAdminWithConn(t *testing.T) {
tests := []struct {
name string
clusterID string
options client.Options
ocmConn *sdk.Connection
elevationReasons []string
wantErr bool
}{
{
// Test that passing a nil OCM connection with elevation reasons returns an error
name: "nil OCM connection",
clusterID: "test-cluster-id",
options: client.Options{},
ocmConn: nil,
elevationReasons: []string{"testing"},
wantErr: true,
},
{
// Test that passing a nil OCM connection without elevation reasons also returns an error
name: "nil OCM connection with no elevation reasons",
clusterID: "test-cluster-id",
options: client.Options{},
ocmConn: nil,
elevationReasons: nil,
wantErr: true,
},
{
// Test that passing an empty cluster ID with nil connection returns an error
name: "empty cluster ID with nil connection",
clusterID: "",
options: client.Options{},
ocmConn: nil,
elevationReasons: []string{"testing"},
wantErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
client, err := NewAsBackplaneClusterAdminWithConn(tt.clusterID, tt.options, tt.ocmConn, tt.elevationReasons...)
if tt.wantErr {
if err == nil {
t.Errorf("NewAsBackplaneClusterAdminWithConn() expected error but got none")
}
} else {
if err != nil {
t.Errorf("NewAsBackplaneClusterAdminWithConn() unexpected error = %v", err)
}
if client == nil {
t.Errorf("NewAsBackplaneClusterAdminWithConn() returned nil client")
}
}
})
}
}
Loading