@ -7,6 +7,9 @@ import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"
"github.com/google/go-cmp/cmp"
@ -104,6 +107,48 @@ func Test_client_Event(t *testing.T) {
}
}
// TestReturnsKubeStatusError ensures HTTP error codes from the Kubernetes API
// server can always be extracted by casting the error to the *kubeapi.Status
// type, as lots of calling code relies on this cast succeeding. Note that
// transport errors are not expected or required to be of type *kubeapi.Status.
func TestReturnsKubeStatusError ( t * testing . T ) {
cl := clientForKubeHandler ( t , http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
w . WriteHeader ( http . StatusForbidden )
_ = json . NewEncoder ( w ) . Encode ( kubeapi . Status { Code : http . StatusForbidden , Message : "test error" } )
} ) )
_ , err := cl . GetSecret ( t . Context ( ) , "test-secret" )
if err == nil {
t . Fatal ( "expected error, got nil" )
}
if st , ok := err . ( * kubeapi . Status ) ; ! ok || st . Code != http . StatusForbidden {
t . Fatalf ( "expected kubeapi.Status with code %d, got %T: %v" , http . StatusForbidden , err , err )
}
}
// clientForKubeHandler creates a client using the externally accessible package
// API to ensure it's testing behaviour as close to prod as possible. The passed
// in handler mocks the Kubernetes API server's responses to any HTTP requests
// made by the client.
func clientForKubeHandler ( t * testing . T , handler http . Handler ) Client {
t . Helper ( )
tmpDir := t . TempDir ( )
rootPathForTests = tmpDir
saDir := filepath . Join ( tmpDir , "var" , "run" , "secrets" , "kubernetes.io" , "serviceaccount" )
_ = os . MkdirAll ( saDir , 0755 )
_ = os . WriteFile ( filepath . Join ( saDir , "token" ) , [ ] byte ( "test-token" ) , 0600 )
_ = os . WriteFile ( filepath . Join ( saDir , "namespace" ) , [ ] byte ( "test-namespace" ) , 0600 )
_ = os . WriteFile ( filepath . Join ( saDir , "ca.crt" ) , [ ] byte ( ca ) , 0644 )
cl , err := New ( "test-client" )
if err != nil {
t . Fatalf ( "New() error = %v" , err )
}
srv := httptest . NewServer ( handler )
t . Cleanup ( srv . Close )
cl . SetURL ( srv . URL )
return cl
}
// args is a set of values for testing a single call to client.kubeAPIRequest.
type args struct {
// wantsMethod is the expected value of 'method' arg.
@ -149,3 +194,34 @@ func fakeKubeAPIRequest(t *testing.T, argSets []args) kubeAPIRequestFunc {
}
return f
}
const ca = ` -- -- - BEGIN CERTIFICATE -- -- -
MIIFEDCCA3igAwIBAgIRANf5NdPojIfj70wMfJVYUg8wDQYJKoZIhvcNAQELBQAw
gZ8xHjAcBgNVBAoTFW1rY2VydCBkZXZlbG9wbWVudCBDQTE6MDgGA1UECwwxZnJv
bWJlcmdlckBzdGFyZHVzdC5sb2NhbCAoTWljaGFlbCBKLiBGcm9tYmVyZ2VyKTFB
MD8GA1UEAww4bWtjZXJ0IGZyb21iZXJnZXJAc3RhcmR1c3QubG9jYWwgKE1pY2hh
ZWwgSi4gRnJvbWJlcmdlcikwHhcNMjMwMjA3MjAzNDE4WhcNMzMwMjA3MjAzNDE4
WjCBnzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMTowOAYDVQQLDDFm
cm9tYmVyZ2VyQHN0YXJkdXN0LmxvY2FsIChNaWNoYWVsIEouIEZyb21iZXJnZXIp
MUEwPwYDVQQDDDhta2NlcnQgZnJvbWJlcmdlckBzdGFyZHVzdC5sb2NhbCAoTWlj
aGFlbCBKLiBGcm9tYmVyZ2VyKTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoC
ggGBAL5uXNnrZ6dgjcvK0Hc7ZNUIRYEWst9qbO0P9H7le08pJ6d9T2BUWruZtVjk
Q12msv5 / bVWHhVk8dZclI9FLXuMsIrocH8bsoP4wruPMyRyp6EedSKODN51fFSRv
/ jHbS5vzUVAWTYy9qYmd6qL0uhsHCZCCT6gfigamHPUFKM3sHDn5ZHWvySMwcyGl
AicmPAIkBWqiCZAkB5 + WM7 + oyRLjmrIalfWIZYxW / rojGLwTfneHv6J5WjVQnpJB
ayWCzCzaiXukK9MeBWeTOe8UfVN0Engd74 / rjLWvjbfC + uZSr6RVkZvs2jANLwPF
zgzBPHgRPfAhszU1NNAMjnNQ47 + OMOTKRt7e6jYzhO5fyO1qVAAvGBqcfpj + JfDk
cccaUMhUvdiGrhGf1V1tN / PislxvALirzcFipjD01isBKwn0fxRugzvJNrjEo8RA
RvbcdeKcwex7M0o / Cd0 + G2B13gZNOFvR33PmG7iTpp7IUrUKfQg28I83Sp8tMY3s
ljJSawIDAQABo0UwQzAOBgNVHQ8BAf8EBAMCAgQwEgYDVR0TAQH / BAgwBgEB / wIB
ADAdBgNVHQ4EFgQU18qto0Fa56kCi / HwfQuC9ECX7cAwDQYJKoZIhvcNAQELBQAD
ggGBAAzs96LwZVOsRSlBdQqMo8oMAvs7HgnYbXt8SqaACLX3 + kJ3cV / vrCE3iJrW
ma4CiQbxS / HqsiZjota5m4lYeEevRnUDpXhp + 7 ugZTiz33Flm1RU99c9UYfQ + 919
ANPAKeqNpoPco / HF5Bz0ocepjcfKQrVZZNTj6noLs8o12FHBLO5976AcF9mqlNfh
8 / F0gDJXq6 + x7VT5y8u0rY004XKPRe3CklRt8kpeMiP6mhRyyUehOaHeIbNx8ubi
Pi44ByN / ueAnuRhF9zYtyZVZZOaSLysJge01tuPXF8rBXGruoJIv35xTTBa9BzaP
YDOGbGn1ZnajdNagHqCba8vjTLDSpqMvgRj3TFrGHdETA2LDQat38uVxX8gxm68K
va5Tyv7n + 6 BQ5YTpJjTPnmSJKaXZrrhdLPvG0OU2TxeEsvbcm5LFQofirOOw86Se
vzF2cQ94mmHRZiEk0Av3NO0jF93ELDrBCuiccVyEKq6TknuvPQlutCXKDOYSEb8I
MHctBg ==
-- -- - END CERTIFICATE -- -- - `