Skip to content

Commit ce5f201

Browse files
EalianisSean Hobbs
andauthored
feat: Enabled webhook in upstream & prod via config. (#330)
* Added configuration for Pod & CRP webhooks to either be service ref or URL (DNS). * Added E2E tests. Co-authored-by: Sean Hobbs <sehobbs@microsoft.com>
1 parent 46b077c commit ce5f201

File tree

13 files changed

+684
-84
lines changed

13 files changed

+684
-84
lines changed

Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,9 @@ install-hub-agent-helm:
140140
--set image.repository=$(REGISTRY)/$(HUB_AGENT_IMAGE_NAME) \
141141
--set image.tag=$(HUB_AGENT_IMAGE_VERSION) \
142142
--set logVerbosity=5 \
143-
--set namespace=fleet-system
143+
--set namespace=fleet-system \
144+
--set enableWebhook=true \
145+
--set webhookClientConnectionType=service
144146

145147
.PHONY: e2e-hub-kubeconfig-secret
146148
e2e-hub-kubeconfig-secret:

charts/hub-agent/templates/deployment.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ spec:
2222
args:
2323
- --leader-elect=true
2424
- --enable-webhook={{ .Values.enableWebhook }}
25+
- --webhook-client-connection-type={{.Values.webhookClientConnectionType}}
2526
- --v={{ .Values.logVerbosity }}
2627
- -add_dir_header
2728
ports:

charts/hub-agent/templates/webhookservice.yaml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# We use a headless service for webhook assuming the apiserver's dns can resolve it.
1+
# The webhook will normally use a service reference with a cluster assigned IP.
22
apiVersion: v1
33
kind: Service
44
metadata:
@@ -7,9 +7,6 @@ metadata:
77
name: fleetwebhook
88
namespace: {{ .Values.namespace }}
99
spec:
10-
clusterIP: None
11-
clusterIPs:
12-
- None
1310
ipFamilies:
1411
- IPv4
1512
ipFamilyPolicy: SingleStack

charts/hub-agent/values.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ image:
1212

1313
logVerbosity: 5
1414

15-
enableWebhook: false
15+
enableWebhook: true
16+
webhookClientConnectionType: service
1617

1718
namespace:
1819
fleet-system

cmd/hubagent/main.go

Lines changed: 13 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
Copyright (c) Microsoft Corporation.
33
Licensed under the MIT license.
44
*/
5+
56
package main
67

78
import (
8-
"context"
99
"flag"
1010
"os"
1111

@@ -25,7 +25,7 @@ import (
2525
"go.goms.io/fleet/pkg/controllers/membercluster"
2626
fleetmetrics "go.goms.io/fleet/pkg/metrics"
2727
"go.goms.io/fleet/pkg/webhook"
28-
//+kubebuilder:scaffold:imports
28+
// +kubebuilder:scaffold:imports
2929
)
3030

3131
var (
@@ -49,7 +49,7 @@ func init() {
4949
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
5050
utilruntime.Must(fleetv1alpha1.AddToScheme(scheme))
5151
utilruntime.Must(workv1alpha1.AddToScheme(scheme))
52-
//+kubebuilder:scaffold:scheme
52+
// +kubebuilder:scaffold:scheme
5353
klog.InitFlags(nil)
5454

5555
metrics.Registry.MustRegister(fleetmetrics.JoinResultMetrics, fleetmetrics.LeaveResultMetrics, fleetmetrics.PlacementApplyFailedCount, fleetmetrics.PlacementApplySucceedCount)
@@ -109,7 +109,7 @@ func main() {
109109
}
110110

111111
if opts.EnableWebhook {
112-
if err := SetupWebhook(mgr); err != nil {
112+
if err := SetupWebhook(mgr, options.WebhookClientConnectionType(opts.WebhookClientConnectionType)); err != nil {
113113
klog.ErrorS(err, "unable to set up webhook")
114114
exitWithErrorFunc()
115115
}
@@ -121,51 +121,29 @@ func main() {
121121
exitWithErrorFunc()
122122
}
123123

124-
//+kubebuilder:scaffold:builder
124+
// +kubebuilder:scaffold:builder
125125

126126
if err := mgr.Start(ctx); err != nil {
127127
klog.ErrorS(err, "problem starting manager")
128128
exitWithErrorFunc()
129129
}
130130
}
131131

132-
// SetupWebhook generate the webhook cert and then setup the webhook configurator
133-
func SetupWebhook(mgr manager.Manager) error {
134-
// Generate self-signed key and crt files in FleetWebhookCertDir for the webhook server to start
135-
caPEM, err := webhook.GenCertificate(FleetWebhookCertDir)
132+
// SetupWebhook generates the webhook cert and then set up the webhook configurator.
133+
func SetupWebhook(mgr manager.Manager, webhookClientConnectionType options.WebhookClientConnectionType) error {
134+
// Generate self-signed key and crt files in FleetWebhookCertDir for the webhook server to start.
135+
w, err := webhook.NewWebhookConfig(mgr, FleetWebhookPort, &webhookClientConnectionType, FleetWebhookCertDir)
136136
if err != nil {
137-
klog.ErrorS(err, "fail to generate certificates for webhook server")
137+
klog.ErrorS(err, "fail to generate WebhookConfig")
138138
return err
139139
}
140-
141-
if err := mgr.Add(&webhookApiserverConfigurator{
142-
mgr: mgr,
143-
caPEM: caPEM,
144-
port: FleetWebhookPort,
145-
}); err != nil {
146-
klog.ErrorS(err, "unable to add webhookApiserverConfigurator")
140+
if err = mgr.Add(w); err != nil {
141+
klog.ErrorS(err, "unable to add WebhookConfig")
147142
return err
148143
}
149-
if err := webhook.AddToManager(mgr); err != nil {
144+
if err = webhook.AddToManager(mgr); err != nil {
150145
klog.ErrorS(err, "unable to register webhooks to the manager")
151146
return err
152147
}
153148
return nil
154149
}
155-
156-
type webhookApiserverConfigurator struct {
157-
mgr manager.Manager
158-
caPEM []byte
159-
port int
160-
}
161-
162-
var _ manager.Runnable = &webhookApiserverConfigurator{}
163-
164-
func (c *webhookApiserverConfigurator) Start(ctx context.Context) error {
165-
klog.V(2).InfoS("setting up webhooks in apiserver from the leader")
166-
if err := webhook.CreateFleetWebhookConfiguration(ctx, c.mgr.GetClient(), c.caPEM, c.port); err != nil {
167-
klog.ErrorS(err, "unable to setup webhook configurations in apiserver")
168-
return err
169-
}
170-
return nil
171-
}

cmd/hubagent/options/options.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Copyright (c) Microsoft Corporation.
33
Licensed under the MIT license.
44
*/
5+
56
package options
67

78
import (
@@ -34,6 +35,8 @@ type Options struct {
3435
MetricsBindAddress string
3536
// EnableWebhook indicates if we will run a webhook
3637
EnableWebhook bool
38+
// Sets the connection type for the webhook.
39+
WebhookClientConnectionType string
3740
// NetworkingAgentsEnabled indicates if we enable network agents
3841
NetworkingAgentsEnabled bool
3942
// ClusterUnhealthyThreshold is the duration of failure for the cluster to be considered unhealthy.
@@ -87,7 +90,8 @@ func (o *Options) AddFlags(flags *flag.FlagSet) {
8790
flags.BoolVar(&o.LeaderElection.LeaderElect, "leader-elect", false, "Start a leader election client and gain leadership before executing the main loop. Enable this when running replicated components for high availability.")
8891
flags.DurationVar(&o.LeaderElection.LeaseDuration.Duration, "leader-lease-duration", 15*time.Second, "This is effectively the maximum duration that a leader can be stopped before someone else will replace it.")
8992
flag.StringVar(&o.LeaderElection.ResourceNamespace, "leader-election-namespace", utils.FleetSystemNamespace, "The namespace in which the leader election resource will be created.")
90-
flag.BoolVar(&o.EnableWebhook, "enable-webhook", false, "If set, the fleet webhook is enabled.")
93+
flag.BoolVar(&o.EnableWebhook, "enable-webhook", true, "If set, the fleet webhook is enabled.")
94+
flag.StringVar(&o.WebhookClientConnectionType, "webhook-client-connection-type", "url", "Sets the connection type used by the webhook client. Only URL or Service is valid.")
9195
flag.BoolVar(&o.NetworkingAgentsEnabled, "networking-agents-enabled", false, "Whether the networking agents are enabled or not.")
9296
flags.DurationVar(&o.ClusterUnhealthyThreshold.Duration, "cluster-unhealthy-threshold", 60*time.Second, "The duration for a member cluster to be in a degraded state before considered unhealthy.")
9397
flags.DurationVar(&o.WorkPendingGracePeriod.Duration, "work-pending-grace-period", 15*time.Second,

cmd/hubagent/options/validation.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,10 @@ func (o *Options) Validate() field.ErrorList {
2929
errs = append(errs, field.Invalid(newPath.Child("WorkPendingGracePeriod"), o.WorkPendingGracePeriod, "must be greater than 0"))
3030
}
3131

32+
connectionType := o.WebhookClientConnectionType
33+
if _, err := parseWebhookClientConnectionString(connectionType); err != nil {
34+
errs = append(errs, field.Invalid(newPath.Child("WebhookClientConnectionType"), o.EnableWebhook, err.Error()))
35+
}
36+
3237
return errs
3338
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
Copyright (c) Microsoft Corporation.
3+
Licensed under the MIT license.
4+
*/
5+
6+
package options
7+
8+
import (
9+
"errors"
10+
"strings"
11+
)
12+
13+
type WebhookClientConnectionType string
14+
15+
const (
16+
URL WebhookClientConnectionType = "url"
17+
Service WebhookClientConnectionType = "service"
18+
)
19+
20+
var (
21+
capabilitiesMap = map[string]WebhookClientConnectionType{
22+
"service": Service,
23+
"url": URL,
24+
}
25+
)
26+
27+
func parseWebhookClientConnectionString(str string) (WebhookClientConnectionType, error) {
28+
t, ok := capabilitiesMap[strings.ToLower(str)]
29+
if !ok {
30+
return "", errors.New("must be \"service\" or \"url\"")
31+
}
32+
return t, nil
33+
}

pkg/webhook/clusterresourceplacement/clusterresourceplacement_webhook.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ import (
1111
fleetv1alpha1 "go.goms.io/fleet/apis/v1alpha1"
1212
)
1313

14+
const (
15+
// ValidationPath is the webhook service path which admission requests are routed to for validating ClusterResourcePlacement resources.
16+
ValidationPath = "/validate-fleet-azure-com-v1alpha1-clusterresourceplacement"
17+
)
18+
1419
func Add(mgr manager.Manager) error {
1520
return (&fleetv1alpha1.ClusterResourcePlacement{}).SetupWebhookWithManager(mgr)
1621
}

pkg/webhook/pod/pod_validating_webhook.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,15 @@ import (
1818
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
1919
)
2020

21+
const (
22+
// ValidationPath is the webhook service path which admission requests are routed to for validating Pod resources.
23+
ValidationPath = "/validate-v1-pod"
24+
)
25+
2126
// Add registers the webhook for K8s bulit-in object types.
2227
func Add(mgr manager.Manager) error {
2328
hookServer := mgr.GetWebhookServer()
24-
hookServer.Register("/validate-v1-pod", &webhook.Admission{Handler: &podValidator{Client: mgr.GetClient()}})
29+
hookServer.Register(ValidationPath, &webhook.Admission{Handler: &podValidator{Client: mgr.GetClient()}})
2530
return nil
2631
}
2732

0 commit comments

Comments
 (0)