Skip to content

Commit d646a93

Browse files
furkhatFurkhat Kasymov Genii Uulu
andauthored
add validation to csr approver with refactoring and near complete integration tests (#182)
* refactored csr v1 & v1beta1 wrapper * integration tests for csr auto approval * more tests & refactoring * test kubelet-serving IPs and DNS match the node * validate "cast-pool" in node name * test v1beta1 * adjust old tests * shorten wait for approval in test * use require for assertions * run more go tests in parallel * run wrapper tests in parallel * add more t.Parallel * add t.Parallel * split integration test * adjust workflows to run tests in parallel * slow TestIntegration * run fewer t.Parallel due to gh actions failure to launch * Revert "add more t.Parallel" This reverts commit 18d191c. * Revert "add t.Parallel" This reverts commit 1f233c8. * Revert "slow TestIntegration" This reverts commit f6bfb80. * increase 10m to 15m * sleep less * GroupVersionKind() returns empty * tiny optimisation * dont lock watchStarted write * allow hostname in dns iff matches node name * reduce cyclomatic complexity of a func --------- Co-authored-by: Furkhat Kasymov Genii Uulu <furkhat@cast.ai>
1 parent 570ad9c commit d646a93

File tree

14 files changed

+2006
-1099
lines changed

14 files changed

+2006
-1099
lines changed

.github/workflows/e2e.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,5 @@ jobs:
5656
CASTAI_API_TOKEN: ${{ secrets.CASTAI_API_TOKEN }}
5757
GCP_CREDENTIALS: ${{ secrets.GCP_CREDENTIALS }}
5858
run: |
59-
go test -timeout 30m ./e2e
59+
go test -timeout 30m -parallel=10 ./e2e
6060

.github/workflows/main.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ jobs:
5454
CGO_ENABLED: 0
5555

5656
- name: Test
57-
run: go test -short -race ./...
57+
run: go test -short -race -timeout 15m ./...
5858

5959
- name: Set up QEMU
6060
uses: docker/setup-qemu-action@v2

.github/workflows/pr.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ jobs:
5252
CGO_ENABLED: 0
5353

5454
- name: Test
55-
run: go test -short -race ./...
55+
run: go test -short -race -timeout 15m ./...
5656

5757
- name: Set up QEMU
5858
uses: docker/setup-qemu-action@v2

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ fix: $(GOLANGCI_LINT)
4141
.PHONY: fix
4242

4343
test:
44-
go test ./... -race
44+
go test ./... -race -parallel=20
4545
.PHONY: test
4646

4747
generate-e2e-client:
4848
go generate ./e2e/client
4949
.PHONY: generate-e2e-client
5050

5151
deploy-loadtest: release
52-
IMAGE_REPOSITORY=$(DOCKER_REPOSITORY) IMAGE_TAG=$(VERSION) ./hack/loadtest/deploy.sh
52+
IMAGE_REPOSITORY=$(DOCKER_REPOSITORY) IMAGE_TAG=$(VERSION) ./hack/loadtest/deploy.sh

internal/actions/csr/approve_csr_handler_test.go

Lines changed: 61 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ package csr
22

33
import (
44
"context"
5+
"crypto/x509"
6+
"crypto/x509/pkix"
57
"errors"
68
"testing"
7-
"time"
89

910
"github.com/sirupsen/logrus"
1011
"github.com/stretchr/testify/require"
@@ -17,6 +18,9 @@ import (
1718
"k8s.io/apimachinery/pkg/runtime/schema"
1819
"k8s.io/client-go/kubernetes/fake"
1920
ktest "k8s.io/client-go/testing"
21+
22+
"github.com/castai/cluster-controller/internal/actions/csr/test"
23+
"github.com/castai/cluster-controller/internal/actions/csr/wrapper"
2024
)
2125

2226
func TestApproveCSRHandler(t *testing.T) {
@@ -27,7 +31,7 @@ func TestApproveCSRHandler(t *testing.T) {
2731
r := require.New(t)
2832

2933
csrRes := getCSR()
30-
client := fake.NewSimpleClientset(csrRes)
34+
client := fake.NewClientset(csrRes)
3135
am := NewApprovalManager(log, client)
3236
csrRes.Status.Conditions = []certv1.CertificateSigningRequestCondition{
3337
{
@@ -36,7 +40,9 @@ func TestApproveCSRHandler(t *testing.T) {
3640
}
3741

3842
ctx := context.Background()
39-
err := am.handle(ctx, log, &Certificate{v1: csrRes})
43+
csr, err := wrapper.NewCSR(client, csrRes)
44+
r.NoError(err)
45+
err = am.handle(ctx, log, csr)
4046
r.NoError(err)
4147
})
4248

@@ -53,12 +59,14 @@ func TestApproveCSRHandler(t *testing.T) {
5359
out := certv1.CertificateSigningRequestList{Items: []certv1.CertificateSigningRequest{*csrRes}}
5460
return true, &out, err
5561
})
56-
client := fake.NewSimpleClientset(csrRes)
62+
client := fake.NewClientset(csrRes)
5763
client.PrependReactor("list", "certificatesigningrequests", fn)
5864

5965
am := NewApprovalManager(log, client)
6066

61-
err := am.handle(context.Background(), log, &Certificate{v1: csrRes})
67+
csr, err := wrapper.NewCSR(client, csrRes)
68+
r.NoError(err)
69+
err = am.handle(context.Background(), log, csr)
6270
r.NoError(err)
6371
})
6472

@@ -67,21 +75,27 @@ func TestApproveCSRHandler(t *testing.T) {
6775

6876
signer := certv1beta1.KubeAPIServerClientKubeletSignerName
6977
csrRes := &certv1beta1.CertificateSigningRequest{
70-
ObjectMeta: metav1.ObjectMeta{Name: "node-csr-123"},
78+
TypeMeta: metav1.TypeMeta{
79+
APIVersion: certv1beta1.SchemeGroupVersion.String(),
80+
Kind: "CertificateSigningRequest",
81+
},
82+
ObjectMeta: metav1.ObjectMeta{
83+
Name: "node-csr-123",
84+
CreationTimestamp: metav1.Now(),
85+
},
7186
Spec: certv1beta1.CertificateSigningRequestSpec{
72-
Request: []byte(`-----BEGIN CERTIFICATE REQUEST-----
73-
MIIBADCBqAIBADBGMRUwEwYDVQQKEwxzeXN0ZW06bm9kZXMxLTArBgNVBAMTJHN5
74-
c3RlbTpub2RlOmdrZS1hbS1nY3AtY2FzdC01ZGM0ZjRlYzBZMBMGByqGSM49AgEG
75-
CCqGSM49AwEHA0IABF/9p5y4t09Y6yAlhF0OthexpL0CEyNHVnVmmbB4jridyJzW
76-
vrcLKbFat0qvJftODQhEA/lqByJepB4YGqQGhregADAKBggqhkjOPQQDAgNHADBE
77-
AiAHVYZXHxxspoV0hcfn2Pdsl89fIPCOFy/K1PqSUR6QNAIgYdt51ZbQt9rgM2BD
78-
39zKjbxU1t82BlrW9/NrmaadNHQ=
79-
-----END CERTIFICATE REQUEST-----`),
80-
Username: "kubelet",
87+
Request: test.NewEncodedCertificateRequest(t, &x509.CertificateRequest{
88+
Subject: pkix.Name{
89+
CommonName: "system:node:gke-am-gcp-cast-pool-5dc4f4ec",
90+
Organization: []string{"system:nodes"},
91+
},
92+
}),
93+
Username: "kubelet-bootstrap",
94+
Usages: []certv1beta1.KeyUsage{certv1beta1.UsageClientAuth},
8195
SignerName: &signer,
8296
},
8397
}
84-
client := fake.NewSimpleClientset(csrRes)
98+
client := fake.NewClientset(csrRes)
8599
// Return NotFound for all v1 resources.
86100
client.PrependReactor("*", "*", func(action ktest.Action) (handled bool, ret runtime.Object, err error) {
87101
if action.GetResource().Version == "v1" {
@@ -95,7 +109,7 @@ func TestApproveCSRHandler(t *testing.T) {
95109
approved.Status.Conditions = []certv1beta1.CertificateSigningRequestCondition{
96110
{
97111
Type: certv1beta1.CertificateApproved,
98-
Reason: ReasonApproved,
112+
Reason: "ReasonApproved",
99113
Message: "approved",
100114
LastUpdateTime: metav1.Now(),
101115
Status: v1.ConditionTrue,
@@ -105,30 +119,39 @@ func TestApproveCSRHandler(t *testing.T) {
105119
})
106120

107121
am := NewApprovalManager(log, client)
108-
err := am.handle(context.Background(), log, &Certificate{v1Beta1: csrRes})
122+
csr, err := wrapper.NewCSR(client, csrRes)
123+
r.NoError(err)
124+
err = am.handle(context.Background(), log, csr)
109125
r.NoError(err)
126+
r.True(csr.Approved())
110127
})
111128

112129
t.Run("approve v1beta1 csr failed", func(t *testing.T) {
113130
r := require.New(t)
114131

115132
signer := certv1beta1.KubeAPIServerClientKubeletSignerName
116133
csrRes := &certv1beta1.CertificateSigningRequest{
117-
ObjectMeta: metav1.ObjectMeta{Name: "node-csr-123"},
134+
TypeMeta: metav1.TypeMeta{
135+
APIVersion: certv1beta1.SchemeGroupVersion.String(),
136+
Kind: "CertificateSigningRequest",
137+
},
138+
ObjectMeta: metav1.ObjectMeta{
139+
Name: "node-csr-123",
140+
CreationTimestamp: metav1.Now(),
141+
},
118142
Spec: certv1beta1.CertificateSigningRequestSpec{
119-
Request: []byte(`-----BEGIN CERTIFICATE REQUEST-----
120-
MIIBADCBqAIBADBGMRUwEwYDVQQKEwxzeXN0ZW06bm9kZXMxLTArBgNVBAMTJHN5
121-
c3RlbTpub2RlOmdrZS1hbS1nY3AtY2FzdC01ZGM0ZjRlYzBZMBMGByqGSM49AgEG
122-
CCqGSM49AwEHA0IABF/9p5y4t09Y6yAlhF0OthexpL0CEyNHVnVmmbB4jridyJzW
123-
vrcLKbFat0qvJftODQhEA/lqByJepB4YGqQGhregADAKBggqhkjOPQQDAgNHADBE
124-
AiAHVYZXHxxspoV0hcfn2Pdsl89fIPCOFy/K1PqSUR6QNAIgYdt51ZbQt9rgM2BD
125-
39zKjbxU1t82BlrW9/NrmaadNHQ=
126-
-----END CERTIFICATE REQUEST-----`),
127-
Username: "kubelet",
143+
Request: test.NewEncodedCertificateRequest(t, &x509.CertificateRequest{
144+
Subject: pkix.Name{
145+
CommonName: "system:node:gke-am-gcp-cast-pool-5dc4f4ec",
146+
Organization: []string{"system:nodes"},
147+
},
148+
}),
149+
Username: "kubelet-bootstrap",
150+
Usages: []certv1beta1.KeyUsage{certv1beta1.UsageClientAuth},
128151
SignerName: &signer,
129152
},
130153
}
131-
client := fake.NewSimpleClientset(csrRes)
154+
client := fake.NewClientset(csrRes)
132155
// Return NotFound for all v1 resources.
133156
client.PrependReactor("*", "*", func(action ktest.Action) (handled bool, ret runtime.Object, err error) {
134157
if action.GetResource().Version == "v1" {
@@ -151,24 +174,20 @@ func TestApproveCSRHandler(t *testing.T) {
151174
})
152175

153176
am := NewApprovalManager(log, client)
154-
err := am.handle(context.Background(), log, &Certificate{v1Beta1: csrRes})
177+
csr, err := wrapper.NewCSR(client, csrRes)
178+
r.NoError(err)
179+
err = am.handle(context.Background(), log, csr)
155180
r.Error(err)
181+
r.False(csr.Approved())
156182
})
157183
}
158184

159-
func TestApproveCSRExponentialBackoff(t *testing.T) {
160-
r := require.New(t)
161-
b := newApproveCSRExponentialBackoff()
162-
var sum time.Duration
163-
for i := 0; i < 10; i++ {
164-
tmp := b.Step()
165-
sum += tmp
166-
}
167-
r.Truef(100 < sum.Seconds(), "actual elapsed seconds %v", sum.Seconds())
168-
}
169-
170185
func getCSR() *certv1.CertificateSigningRequest {
171186
return &certv1.CertificateSigningRequest{
187+
TypeMeta: metav1.TypeMeta{
188+
APIVersion: certv1.SchemeGroupVersion.String(),
189+
Kind: "CertificateSigningRequest",
190+
},
172191
ObjectMeta: metav1.ObjectMeta{Name: "node-csr-123"},
173192
Spec: certv1.CertificateSigningRequestSpec{
174193
Request: []byte(`-----BEGIN CERTIFICATE REQUEST-----
@@ -180,7 +199,7 @@ AiAHVYZXHxxspoV0hcfn2Pdsl89fIPCOFy/K1PqSUR6QNAIgYdt51ZbQt9rgM2BD
180199
39zKjbxU1t82BlrW9/NrmaadNHQ=
181200
-----END CERTIFICATE REQUEST-----`),
182201
SignerName: certv1.KubeAPIServerClientKubeletSignerName,
183-
Usages: []certv1.KeyUsage{"kubelet"},
202+
Usages: []certv1.KeyUsage{certv1.UsageClientAuth},
184203
Username: "kubelet-bootstrap",
185204
},
186205
// Status: certv1.CertificateSigningRequestStatus{},.

0 commit comments

Comments
 (0)