Skip to content

Commit 4a59ada

Browse files
committed
test: Extract common variable testing funcs
Also refactor handler interface definitions for cleaner separation between mutation and lifecycle handlers.
1 parent 5a05bc4 commit 4a59ada

File tree

24 files changed

+290
-204
lines changed

24 files changed

+290
-204
lines changed

common/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module github.com/d2iq-labs/capi-runtime-extensions/common
66
go 1.21
77

88
require (
9+
github.com/onsi/gomega v1.27.10
910
github.com/spf13/pflag v1.0.5
1011
k8s.io/apiextensions-apiserver v0.28.1
1112
k8s.io/apimachinery v0.28.1

common/pkg/handlers/interfaces.go

Lines changed: 1 addition & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -3,75 +3,6 @@
33

44
package handlers
55

6-
import (
7-
"context"
8-
9-
"github.com/spf13/pflag"
10-
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
11-
)
12-
13-
type NamedHandler interface {
6+
type Named interface {
147
Name() string
158
}
16-
17-
type FlagConfigurableHandler interface {
18-
AddFlags(prefix string, fs *pflag.FlagSet)
19-
}
20-
21-
type BeforeClusterCreateLifecycleHandler interface {
22-
BeforeClusterCreate(
23-
context.Context,
24-
*runtimehooksv1.BeforeClusterCreateRequest,
25-
*runtimehooksv1.BeforeClusterCreateResponse,
26-
)
27-
}
28-
type AfterControlPlaneInitializedLifecycleHandler interface {
29-
AfterControlPlaneInitialized(
30-
context.Context,
31-
*runtimehooksv1.AfterControlPlaneInitializedRequest,
32-
*runtimehooksv1.AfterControlPlaneInitializedResponse,
33-
)
34-
}
35-
type BeforeClusterUpgradeLifecycleHandler interface {
36-
BeforeClusterUpgrade(
37-
context.Context,
38-
*runtimehooksv1.BeforeClusterUpgradeRequest,
39-
*runtimehooksv1.BeforeClusterUpgradeResponse,
40-
)
41-
}
42-
type AfterControlPlaneUpgradeLifecycleHandler interface {
43-
AfterControlPlaneUpgrade(
44-
context.Context,
45-
*runtimehooksv1.AfterControlPlaneUpgradeRequest,
46-
*runtimehooksv1.AfterControlPlaneUpgradeResponse,
47-
)
48-
}
49-
type BeforeClusterDeleteLifecycleHandler interface {
50-
BeforeClusterDelete(
51-
context.Context,
52-
*runtimehooksv1.BeforeClusterDeleteRequest,
53-
*runtimehooksv1.BeforeClusterDeleteResponse,
54-
)
55-
}
56-
57-
type DiscoverVariablesMutationHandler interface {
58-
DiscoverVariables(
59-
context.Context,
60-
*runtimehooksv1.DiscoverVariablesRequest,
61-
*runtimehooksv1.DiscoverVariablesResponse,
62-
)
63-
}
64-
type GeneratePatchesMutationHandler interface {
65-
GeneratePatches(
66-
context.Context,
67-
*runtimehooksv1.GeneratePatchesRequest,
68-
*runtimehooksv1.GeneratePatchesResponse,
69-
)
70-
}
71-
type ValidateTopologyMutationHandler interface {
72-
ValidateTopology(
73-
context.Context,
74-
*runtimehooksv1.ValidateTopologyRequest,
75-
*runtimehooksv1.ValidateTopologyResponse,
76-
)
77-
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2023 D2iQ, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package lifecycle
5+
6+
import (
7+
"context"
8+
9+
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
10+
)
11+
12+
type BeforeClusterCreate interface {
13+
BeforeClusterCreate(
14+
context.Context,
15+
*runtimehooksv1.BeforeClusterCreateRequest,
16+
*runtimehooksv1.BeforeClusterCreateResponse,
17+
)
18+
}
19+
type AfterControlPlaneInitialized interface {
20+
AfterControlPlaneInitialized(
21+
context.Context,
22+
*runtimehooksv1.AfterControlPlaneInitializedRequest,
23+
*runtimehooksv1.AfterControlPlaneInitializedResponse,
24+
)
25+
}
26+
type BeforeClusterUpgrade interface {
27+
BeforeClusterUpgrade(
28+
context.Context,
29+
*runtimehooksv1.BeforeClusterUpgradeRequest,
30+
*runtimehooksv1.BeforeClusterUpgradeResponse,
31+
)
32+
}
33+
type AfterControlPlaneUpgrade interface {
34+
AfterControlPlaneUpgrade(
35+
context.Context,
36+
*runtimehooksv1.AfterControlPlaneUpgradeRequest,
37+
*runtimehooksv1.AfterControlPlaneUpgradeResponse,
38+
)
39+
}
40+
type BeforeClusterDelete interface {
41+
BeforeClusterDelete(
42+
context.Context,
43+
*runtimehooksv1.BeforeClusterDeleteRequest,
44+
*runtimehooksv1.BeforeClusterDeleteResponse,
45+
)
46+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2023 D2iQ, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package mutation
5+
6+
import (
7+
"context"
8+
9+
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
10+
)
11+
12+
type DiscoverVariables interface {
13+
DiscoverVariables(
14+
context.Context,
15+
*runtimehooksv1.DiscoverVariablesRequest,
16+
*runtimehooksv1.DiscoverVariablesResponse,
17+
)
18+
}
19+
type GeneratePatches interface {
20+
GeneratePatches(
21+
context.Context,
22+
*runtimehooksv1.GeneratePatchesRequest,
23+
*runtimehooksv1.GeneratePatchesResponse,
24+
)
25+
}
26+
type ValidateTopology interface {
27+
ValidateTopology(
28+
context.Context,
29+
*runtimehooksv1.ValidateTopologyRequest,
30+
*runtimehooksv1.ValidateTopologyResponse,
31+
)
32+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2023 D2iQ, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package patterns
5+
6+
const (
7+
// See: https://github.com/distribution/reference/blob/v0.5.0/regexp.go#L53
8+
NameSeparator = `(?:[._]|__|[-]+)`
9+
10+
// See: https://github.com/distribution/reference/blob/v0.5.0/regexp.go#L123C18-L123C65
11+
PathComponent = Alphanumeric + `(` + NameSeparator + Alphanumeric + `)*`
12+
13+
// See: https://github.com/distribution/reference/blob/v0.5.0/regexp.go#L130
14+
ImageRegistry = `(` + DNS1123Subdomain + `|` + IPv6 + `)` + OptionalPort + `(/` + PathComponent + `)*`
15+
)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright 2023 D2iQ, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package patterns
5+
6+
const (
7+
// See: https://github.com/distribution/reference/blob/v0.5.0/regexp.go#L44C2-L44C28
8+
Alphanumeric = `[a-z0-9]+`
9+
)

common/pkg/openapi/patterns/net.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2023 D2iQ, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package patterns
5+
6+
const (
7+
// See: https://github.com/distribution/reference/blob/v0.5.0/regexp.go#L91
8+
IPv6 = `\[(?:[a-fA-F0-9:]+)\]`
9+
10+
Port = `:[0-9]+`
11+
12+
OptionalPort = `(` + Port + `)?`
13+
)

common/pkg/server/server.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ import (
1515
ctrl "sigs.k8s.io/controller-runtime"
1616

1717
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/handlers"
18+
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/handlers/lifecycle"
19+
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/handlers/mutation"
1820
)
1921

2022
type Server struct {
21-
allExtensionHandlers []handlers.NamedHandler
23+
allExtensionHandlers []handlers.Named
2224

2325
webhookPort int
2426
webhookCertDir string
@@ -28,7 +30,7 @@ type Server struct {
2830
enabledHandlers []string
2931
}
3032

31-
func NewServer(extensionHandlers ...handlers.NamedHandler) *Server {
33+
func NewServer(extensionHandlers ...handlers.Named) *Server {
3234
// catalog contains all information about RuntimeHooks.
3335
catalog := runtimecatalog.New()
3436

@@ -87,7 +89,7 @@ func (s *Server) Start(ctx context.Context) error {
8789
continue
8890
}
8991

90-
if t, ok := h.(handlers.BeforeClusterCreateLifecycleHandler); ok {
92+
if t, ok := h.(lifecycle.BeforeClusterCreate); ok {
9193
if err := webhookServer.AddExtensionHandler(server.ExtensionHandler{
9294
Hook: runtimehooksv1.BeforeClusterCreate,
9395
Name: strings.ToLower(h.Name()),
@@ -98,7 +100,7 @@ func (s *Server) Start(ctx context.Context) error {
98100
}
99101
}
100102

101-
if t, ok := h.(handlers.AfterControlPlaneInitializedLifecycleHandler); ok {
103+
if t, ok := h.(lifecycle.AfterControlPlaneInitialized); ok {
102104
if err := webhookServer.AddExtensionHandler(server.ExtensionHandler{
103105
Hook: runtimehooksv1.AfterControlPlaneInitialized,
104106
Name: strings.ToLower(h.Name()),
@@ -109,7 +111,7 @@ func (s *Server) Start(ctx context.Context) error {
109111
}
110112
}
111113

112-
if t, ok := h.(handlers.BeforeClusterUpgradeLifecycleHandler); ok {
114+
if t, ok := h.(lifecycle.BeforeClusterUpgrade); ok {
113115
if err := webhookServer.AddExtensionHandler(server.ExtensionHandler{
114116
Hook: runtimehooksv1.BeforeClusterUpgrade,
115117
Name: strings.ToLower(h.Name()),
@@ -120,7 +122,7 @@ func (s *Server) Start(ctx context.Context) error {
120122
}
121123
}
122124

123-
if t, ok := h.(handlers.AfterControlPlaneUpgradeLifecycleHandler); ok {
125+
if t, ok := h.(lifecycle.AfterControlPlaneUpgrade); ok {
124126
if err := webhookServer.AddExtensionHandler(server.ExtensionHandler{
125127
Hook: runtimehooksv1.AfterControlPlaneUpgrade,
126128
Name: h.Name(),
@@ -131,7 +133,7 @@ func (s *Server) Start(ctx context.Context) error {
131133
}
132134
}
133135

134-
if t, ok := h.(handlers.BeforeClusterDeleteLifecycleHandler); ok {
136+
if t, ok := h.(lifecycle.BeforeClusterDelete); ok {
135137
if err := webhookServer.AddExtensionHandler(server.ExtensionHandler{
136138
Hook: runtimehooksv1.BeforeClusterDelete,
137139
Name: strings.ToLower(h.Name()),
@@ -142,7 +144,7 @@ func (s *Server) Start(ctx context.Context) error {
142144
}
143145
}
144146

145-
if t, ok := h.(handlers.DiscoverVariablesMutationHandler); ok {
147+
if t, ok := h.(mutation.DiscoverVariables); ok {
146148
if err := webhookServer.AddExtensionHandler(server.ExtensionHandler{
147149
Hook: runtimehooksv1.DiscoverVariables,
148150
Name: strings.ToLower(h.Name()),
@@ -153,7 +155,7 @@ func (s *Server) Start(ctx context.Context) error {
153155
}
154156
}
155157

156-
if t, ok := h.(handlers.GeneratePatchesMutationHandler); ok {
158+
if t, ok := h.(mutation.GeneratePatches); ok {
157159
if err := webhookServer.AddExtensionHandler(server.ExtensionHandler{
158160
Hook: runtimehooksv1.GeneratePatches,
159161
Name: strings.ToLower(h.Name()),
@@ -164,7 +166,7 @@ func (s *Server) Start(ctx context.Context) error {
164166
}
165167
}
166168

167-
if t, ok := h.(handlers.ValidateTopologyMutationHandler); ok {
169+
if t, ok := h.(mutation.ValidateTopology); ok {
168170
if err := webhookServer.AddExtensionHandler(server.ExtensionHandler{
169171
Hook: runtimehooksv1.ValidateTopology,
170172
Name: strings.ToLower(h.Name()),
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright 2023 D2iQ, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package capitest
5+
6+
import (
7+
"context"
8+
"encoding/json"
9+
"testing"
10+
11+
"github.com/onsi/gomega"
12+
"github.com/onsi/gomega/gstruct"
13+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
14+
"k8s.io/apimachinery/pkg/util/validation/field"
15+
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
16+
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
17+
18+
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/handlers/mutation"
19+
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/testutils/openapi"
20+
)
21+
22+
type VariableTestDef struct {
23+
Name string
24+
Vals any
25+
ExpectError bool
26+
}
27+
28+
func ValidateVariable[T mutation.DiscoverVariables](
29+
t *testing.T,
30+
variableName string,
31+
variableSchema *clusterv1.VariableSchema,
32+
handlerCreator func() T,
33+
variableTestDefs ...VariableTestDef,
34+
) {
35+
t.Helper()
36+
37+
t.Parallel()
38+
39+
for idx := range variableTestDefs {
40+
tt := variableTestDefs[idx]
41+
42+
t.Run(tt.Name, func(t *testing.T) {
43+
t.Parallel()
44+
45+
g := gomega.NewWithT(t)
46+
h := handlerCreator()
47+
resp := &runtimehooksv1.DiscoverVariablesResponse{}
48+
h.DiscoverVariables(
49+
context.Background(),
50+
&runtimehooksv1.DiscoverVariablesRequest{},
51+
resp,
52+
)
53+
54+
g.Expect(resp.Status).To(gomega.Equal(runtimehooksv1.ResponseStatusSuccess))
55+
g.Expect(resp.Variables).To(gomega.HaveLen(1))
56+
57+
variable := resp.Variables[0]
58+
g.Expect(variable).To(gstruct.MatchFields(gstruct.IgnoreExtras, gstruct.Fields{
59+
"Name": gomega.Equal(variableName),
60+
"Required": gomega.BeFalse(),
61+
"Schema": gomega.Equal(*variableSchema),
62+
}))
63+
64+
encodedVals, err := json.Marshal(tt.Vals)
65+
g.Expect(err).NotTo(gomega.HaveOccurred())
66+
67+
validateErr := openapi.ValidateClusterVariable(
68+
&clusterv1.ClusterVariable{
69+
Name: variableName,
70+
Value: apiextensionsv1.JSON{Raw: encodedVals},
71+
},
72+
&variable,
73+
field.NewPath(variableName),
74+
).ToAggregate()
75+
76+
if tt.ExpectError {
77+
g.Expect(validateErr).To(gomega.HaveOccurred())
78+
} else {
79+
g.Expect(validateErr).NotTo(gomega.HaveOccurred())
80+
}
81+
})
82+
}
83+
}

docs/content/http-proxy.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ spec:
3434
- name: proxy
3535
value:
3636
http: http://example.com
37-
https: http://example.com
37+
https: https://example.com
3838
no:
39-
- http://no-proxy-1.example.com
40-
- http://no-proxy-2.example.com
39+
- no-proxy-1.example.com
40+
- no-proxy-2.example.com
4141
```
4242
4343
Applying this configuration will result in new bootstrap files on the `KubeadmControlPlaneTemplate`

0 commit comments

Comments
 (0)