github.com/oam-dev/cluster-gateway@v1.9.0/pkg/apis/cluster/v1alpha1/transport_test.go (about)

     1  package v1alpha1
     2  
     3  import (
     4  	"context"
     5  	"net"
     6  	"net/http"
     7  	"net/url"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    14  	k8snet "k8s.io/apimachinery/pkg/util/net"
    15  	"k8s.io/client-go/rest"
    16  	"k8s.io/utils/pointer"
    17  )
    18  
    19  func TestClusterRestConfigConversion(t *testing.T) {
    20  	testToken := "test-token"
    21  	testCAData := []byte(`test-ca`)
    22  	testCertData := []byte(`test-cert`)
    23  	testKeyData := []byte(`test-key`)
    24  	proxyURLData := []byte(`socks5://localhost:1080`)
    25  	proxyURL, _ := url.Parse(string(proxyURLData))
    26  	testDialFunc := func(ctx context.Context, net, addr string) (net.Conn, error) {
    27  		return nil, nil
    28  	}
    29  	DialerGetter = func(ctx context.Context) (k8snet.DialFunc, error) {
    30  		return testDialFunc, nil
    31  	}
    32  	cases := []struct {
    33  		name           string
    34  		clusterGateway *ClusterGateway
    35  		expectedCfg    *rest.Config
    36  		expectFailure  bool
    37  	}{
    38  		{
    39  			name: "normal cluster-gateway with SA token + host-port should work",
    40  			clusterGateway: &ClusterGateway{
    41  				Spec: ClusterGatewaySpec{
    42  					Access: ClusterAccess{
    43  						Endpoint: &ClusterEndpoint{
    44  							Type: ClusterEndpointTypeConst,
    45  							Const: &ClusterEndpointConst{
    46  								Address:  "https://foo.bar:33",
    47  								CABundle: testCAData,
    48  							},
    49  						},
    50  						Credential: &ClusterAccessCredential{
    51  							Type:                CredentialTypeServiceAccountToken,
    52  							ServiceAccountToken: testToken,
    53  						},
    54  					},
    55  				},
    56  			},
    57  			expectedCfg: &rest.Config{
    58  				Host:        "https://foo.bar:33",
    59  				BearerToken: testToken,
    60  				Timeout:     40 * time.Second,
    61  				TLSClientConfig: rest.TLSClientConfig{
    62  					ServerName: "foo.bar",
    63  					CAData:     testCAData,
    64  				},
    65  			},
    66  		},
    67  		{
    68  			name: "normal cluster-gateway with X509 + host-port should work",
    69  			clusterGateway: &ClusterGateway{
    70  				Spec: ClusterGatewaySpec{
    71  					Access: ClusterAccess{
    72  						Endpoint: &ClusterEndpoint{
    73  							Type: ClusterEndpointTypeConst,
    74  							Const: &ClusterEndpointConst{
    75  								Address:  "https://foo.bar:33",
    76  								CABundle: testCAData,
    77  							},
    78  						},
    79  						Credential: &ClusterAccessCredential{
    80  							Type: CredentialTypeX509Certificate,
    81  							X509: &X509{
    82  								Certificate: testCertData,
    83  								PrivateKey:  testKeyData,
    84  							},
    85  						},
    86  					},
    87  				},
    88  			},
    89  			expectedCfg: &rest.Config{
    90  				Host:    "https://foo.bar:33",
    91  				Timeout: 40 * time.Second,
    92  				TLSClientConfig: rest.TLSClientConfig{
    93  					ServerName: "foo.bar",
    94  					CAData:     testCAData,
    95  					CertData:   testCertData,
    96  					KeyData:    testKeyData,
    97  				},
    98  			},
    99  		},
   100  		{
   101  			name: "https port defaulting should work",
   102  			clusterGateway: &ClusterGateway{
   103  				Spec: ClusterGatewaySpec{
   104  					Access: ClusterAccess{
   105  						Endpoint: &ClusterEndpoint{
   106  							Type: ClusterEndpointTypeConst,
   107  							Const: &ClusterEndpointConst{
   108  								Address:  "https://foo.bar",
   109  								CABundle: testCAData,
   110  							},
   111  						},
   112  						Credential: &ClusterAccessCredential{
   113  							Type:                CredentialTypeServiceAccountToken,
   114  							ServiceAccountToken: testToken,
   115  						},
   116  					},
   117  				},
   118  			},
   119  			expectedCfg: &rest.Config{
   120  				Host:        "https://foo.bar",
   121  				Timeout:     40 * time.Second,
   122  				BearerToken: testToken,
   123  				TLSClientConfig: rest.TLSClientConfig{
   124  					ServerName: "foo.bar",
   125  					CAData:     testCAData,
   126  				},
   127  			},
   128  		},
   129  		{
   130  			name: "insecure (no CA bundle) should work",
   131  			clusterGateway: &ClusterGateway{
   132  				Spec: ClusterGatewaySpec{
   133  					Access: ClusterAccess{
   134  						Endpoint: &ClusterEndpoint{
   135  							Type: ClusterEndpointTypeConst,
   136  							Const: &ClusterEndpointConst{
   137  								Address:  "https://foo.bar:33",
   138  								Insecure: pointer.Bool(true),
   139  							},
   140  						},
   141  						Credential: &ClusterAccessCredential{
   142  							Type:                CredentialTypeServiceAccountToken,
   143  							ServiceAccountToken: testToken,
   144  						},
   145  					},
   146  				},
   147  			},
   148  			expectedCfg: &rest.Config{
   149  				Host:        "https://foo.bar:33",
   150  				Timeout:     40 * time.Second,
   151  				BearerToken: testToken,
   152  				TLSClientConfig: rest.TLSClientConfig{
   153  					ServerName: "foo.bar",
   154  					Insecure:   true,
   155  				},
   156  			},
   157  		},
   158  		{
   159  			name: "cluster-proxy egress should work",
   160  			clusterGateway: &ClusterGateway{
   161  				ObjectMeta: metav1.ObjectMeta{
   162  					Name: "my-cluster",
   163  				},
   164  				Spec: ClusterGatewaySpec{
   165  					Access: ClusterAccess{
   166  						Endpoint: &ClusterEndpoint{
   167  							Type: ClusterEndpointTypeClusterProxy,
   168  						},
   169  						Credential: &ClusterAccessCredential{
   170  							Type:                CredentialTypeServiceAccountToken,
   171  							ServiceAccountToken: testToken,
   172  						},
   173  					},
   174  				},
   175  			},
   176  			expectedCfg: &rest.Config{
   177  				Host:        "my-cluster",
   178  				Timeout:     40 * time.Second,
   179  				BearerToken: testToken,
   180  				Dial:        testDialFunc,
   181  				TLSClientConfig: rest.TLSClientConfig{
   182  					Insecure: true,
   183  				},
   184  			},
   185  		},
   186  		{
   187  			name: "proxy-url should work",
   188  			clusterGateway: &ClusterGateway{
   189  				ObjectMeta: metav1.ObjectMeta{
   190  					Name: "my-cluster",
   191  				},
   192  				Spec: ClusterGatewaySpec{
   193  					Access: ClusterAccess{
   194  						Endpoint: &ClusterEndpoint{
   195  							Type: ClusterEndpointTypeConst,
   196  							Const: &ClusterEndpointConst{
   197  								Address:  "https://foo.bar:33",
   198  								ProxyURL: pointer.String(string(proxyURLData)),
   199  							},
   200  						},
   201  						Credential: &ClusterAccessCredential{
   202  							Type:                CredentialTypeServiceAccountToken,
   203  							ServiceAccountToken: testToken,
   204  						},
   205  					},
   206  				},
   207  			},
   208  			expectedCfg: &rest.Config{
   209  				Host:        "https://foo.bar:33",
   210  				Timeout:     40 * time.Second,
   211  				BearerToken: testToken,
   212  				Proxy:       http.ProxyURL(proxyURL),
   213  				TLSClientConfig: rest.TLSClientConfig{
   214  					ServerName: "foo.bar",
   215  				},
   216  			},
   217  		},
   218  		{
   219  			name: "dynamic credential: service account token",
   220  			clusterGateway: &ClusterGateway{
   221  				ObjectMeta: metav1.ObjectMeta{
   222  					Name: "my-cluster",
   223  				},
   224  				Spec: ClusterGatewaySpec{
   225  					Access: ClusterAccess{
   226  						Endpoint: &ClusterEndpoint{
   227  							Type: ClusterEndpointTypeConst,
   228  							Const: &ClusterEndpointConst{
   229  								Address:  "https://k8s.example.com",
   230  								CABundle: testCAData,
   231  							},
   232  						},
   233  						Credential: &ClusterAccessCredential{
   234  							Type:                CredentialTypeDynamic,
   235  							ServiceAccountToken: testToken,
   236  						},
   237  					},
   238  				},
   239  			},
   240  			expectedCfg: &rest.Config{
   241  				Host:        "https://k8s.example.com",
   242  				Timeout:     40 * time.Second,
   243  				BearerToken: testToken,
   244  				TLSClientConfig: rest.TLSClientConfig{
   245  					ServerName: "k8s.example.com",
   246  					CAData:     testCAData,
   247  				},
   248  			},
   249  		},
   250  		{
   251  			name: "dynamic credential: certificate + private key",
   252  			clusterGateway: &ClusterGateway{
   253  				ObjectMeta: metav1.ObjectMeta{
   254  					Name: "my-cluster",
   255  				},
   256  				Spec: ClusterGatewaySpec{
   257  					Access: ClusterAccess{
   258  						Endpoint: &ClusterEndpoint{
   259  							Type: ClusterEndpointTypeConst,
   260  							Const: &ClusterEndpointConst{
   261  								Address:  "https://k8s.example.com",
   262  								CABundle: testCAData,
   263  							},
   264  						},
   265  						Credential: &ClusterAccessCredential{
   266  							Type: CredentialTypeDynamic,
   267  							X509: &X509{
   268  								Certificate: testCertData,
   269  								PrivateKey:  testKeyData,
   270  							},
   271  						},
   272  					},
   273  				},
   274  			},
   275  			expectedCfg: &rest.Config{
   276  				Host:    "https://k8s.example.com",
   277  				Timeout: 40 * time.Second,
   278  				TLSClientConfig: rest.TLSClientConfig{
   279  					ServerName: "k8s.example.com",
   280  					CertData:   testCertData,
   281  					KeyData:    testKeyData,
   282  					CAData:     testCAData,
   283  				},
   284  			},
   285  		},
   286  	}
   287  	for _, c := range cases {
   288  		t.Run(c.name, func(t *testing.T) {
   289  			cfg, err := NewConfigFromCluster(context.TODO(), c.clusterGateway)
   290  			if err != nil {
   291  				if c.expectFailure {
   292  					return
   293  				}
   294  				require.NoError(t, err)
   295  			}
   296  			if cfg.Dial != nil {
   297  				assert.ObjectsAreEqual(c.expectedCfg.Dial, cfg.Dial)
   298  				c.expectedCfg.Dial = nil
   299  				cfg.Dial = nil
   300  			}
   301  			if cfg.Proxy != nil {
   302  				assert.NotNil(t, c.expectedCfg.Proxy)
   303  				cfg.Proxy = nil
   304  				c.expectedCfg.Proxy = nil
   305  			}
   306  			assert.Equal(t, c.expectedCfg, cfg)
   307  		})
   308  	}
   309  
   310  }