Skip to content

Commit

Permalink
[DCA][Admission Controller] Use ReinvocationPolicy + make it configur…
Browse files Browse the repository at this point in the history
…able
  • Loading branch information
ahmed-mez committed Mar 30, 2022
1 parent e61f892 commit 01a5330
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 10 deletions.
23 changes: 13 additions & 10 deletions pkg/clusteragent/admission/controllers/webhook/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type Config struct {
svcPort int32
timeout int32
failurePolicy string
reinvocationPolicy string
}

// NewConfig creates a webhook controller configuration
Expand All @@ -42,19 +43,21 @@ func NewConfig(admissionV1Enabled, namespaceSelectorEnabled bool) Config {
svcPort: int32(443),
timeout: config.Datadog.GetInt32("admission_controller.timeout_seconds"),
failurePolicy: config.Datadog.GetString("admission_controller.failure_policy"),
reinvocationPolicy: config.Datadog.GetString("admission_controller.reinvocation_policy"),
}
}

func (w *Config) getWebhookName() string { return w.webhookName }
func (w *Config) getSecretName() string { return w.secretName }
func (w *Config) getSecretNs() string { return w.namespace }
func (w *Config) useAdmissionV1() bool { return w.admissionV1Enabled }
func (w *Config) useNamespaceSelector() bool { return w.namespaceSelectorEnabled }
func (w *Config) getServiceNs() string { return w.namespace }
func (w *Config) getServiceName() string { return w.svcName }
func (w *Config) getServicePort() int32 { return w.svcPort }
func (w *Config) getTimeout() int32 { return w.timeout }
func (w *Config) getFailurePolicy() string { return w.failurePolicy }
func (w *Config) getWebhookName() string { return w.webhookName }
func (w *Config) getSecretName() string { return w.secretName }
func (w *Config) getSecretNs() string { return w.namespace }
func (w *Config) useAdmissionV1() bool { return w.admissionV1Enabled }
func (w *Config) useNamespaceSelector() bool { return w.namespaceSelectorEnabled }
func (w *Config) getServiceNs() string { return w.namespace }
func (w *Config) getServiceName() string { return w.svcName }
func (w *Config) getServicePort() int32 { return w.svcPort }
func (w *Config) getTimeout() int32 { return w.timeout }
func (w *Config) getFailurePolicy() string { return w.failurePolicy }
func (w *Config) getReinvocationPolicy() string { return w.reinvocationPolicy }
func (w *Config) configName(suffix string) string {
return strings.ReplaceAll(fmt.Sprintf("%s.%s", w.webhookName, suffix), "-", ".")
}
15 changes: 15 additions & 0 deletions pkg/clusteragent/admission/controllers/webhook/controller_v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ func (c *ControllerV1) getWebhookSkeleton(nameSuffix, path string) admiv1.Mutati
port := c.config.getServicePort()
timeout := c.config.getTimeout()
failurePolicy := c.getAdmiV1FailurePolicy()
reinvocationPolicy := c.getReinvocationPolicy()
webhook := admiv1.MutatingWebhook{
Name: c.config.configName(nameSuffix),
ClientConfig: admiv1.WebhookClientConfig{
Expand All @@ -226,6 +227,7 @@ func (c *ControllerV1) getWebhookSkeleton(nameSuffix, path string) admiv1.Mutati
},
},
},
ReinvocationPolicy: &reinvocationPolicy,
FailurePolicy: &failurePolicy,
MatchPolicy: &matchPolicy,
SideEffects: &sideEffects,
Expand Down Expand Up @@ -256,3 +258,16 @@ func (c *ControllerV1) getAdmiV1FailurePolicy() admiv1.FailurePolicyType {
return admiv1.Ignore
}
}

func (c *ControllerV1) getReinvocationPolicy() admiv1.ReinvocationPolicyType {
policy := strings.ToLower(c.config.getReinvocationPolicy())
switch policy {
case "ifneeded":
return admiv1.IfNeededReinvocationPolicy
case "never":
return admiv1.NeverReinvocationPolicy
default:
log.Warnf("Unknown reinvocation policy %q - defaulting to %q", policy, admiv1.IfNeededReinvocationPolicy)
return admiv1.IfNeededReinvocationPolicy
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ func TestAdmissionControllerFailureModeFail(t *testing.T) {

func TestGenerateTemplatesV1(t *testing.T) {
mockConfig := config.Mock()
defaultReinvocationPolicy := admiv1.IfNeededReinvocationPolicy
failurePolicy := admiv1.Ignore
matchPolicy := admiv1.Exact
sideEffects := admiv1.SideEffectClassNone
Expand Down Expand Up @@ -202,6 +203,7 @@ func TestGenerateTemplatesV1(t *testing.T) {
},
},
},
ReinvocationPolicy: &defaultReinvocationPolicy,
FailurePolicy: &failurePolicy,
MatchPolicy: &matchPolicy,
SideEffects: &sideEffects,
Expand Down Expand Up @@ -382,6 +384,7 @@ func TestGenerateTemplatesV1(t *testing.T) {
}

func TestGetWebhookSkeletonV1(t *testing.T) {
defaultReinvocationPolicy := admiv1.IfNeededReinvocationPolicy
failurePolicy := admiv1.Ignore
matchPolicy := admiv1.Exact
sideEffects := admiv1.SideEffectClassNone
Expand Down Expand Up @@ -412,6 +415,7 @@ func TestGetWebhookSkeletonV1(t *testing.T) {
},
},
},
ReinvocationPolicy: &defaultReinvocationPolicy,
FailurePolicy: &failurePolicy,
MatchPolicy: &matchPolicy,
SideEffects: &sideEffects,
Expand Down Expand Up @@ -528,3 +532,42 @@ func validateV1(w *admiv1.MutatingWebhookConfiguration, s *corev1.Secret) error

return nil
}

func TestAdmissionControllerReinvocationPolicyV1(t *testing.T) {
f := newFixtureV1(t)
c := f.run(t)
c.config = NewConfig(true, false)

defaultValue := config.Datadog.Get("admission_controller.reinvocation_policy")
defer config.Datadog.Set("admission_controller.reinvocation_policy", defaultValue)

config.Datadog.Set("admission_controller.reinvocation_policy", "IfNeeded")
c.config = NewConfig(true, false)
webhook := c.getWebhookSkeleton("foo", "/bar")
assert.Equal(t, admiv1.IfNeededReinvocationPolicy, *webhook.ReinvocationPolicy)

config.Datadog.Set("admission_controller.reinvocation_policy", "ifneeded")
c.config = NewConfig(true, false)
webhook = c.getWebhookSkeleton("foo", "/bar")
assert.Equal(t, admiv1.IfNeededReinvocationPolicy, *webhook.ReinvocationPolicy)

config.Datadog.Set("admission_controller.reinvocation_policy", "Never")
c.config = NewConfig(true, false)
webhook = c.getWebhookSkeleton("foo", "/bar")
assert.Equal(t, admiv1.NeverReinvocationPolicy, *webhook.ReinvocationPolicy)

config.Datadog.Set("admission_controller.reinvocation_policy", "never")
c.config = NewConfig(true, false)
webhook = c.getWebhookSkeleton("foo", "/bar")
assert.Equal(t, admiv1.NeverReinvocationPolicy, *webhook.ReinvocationPolicy)

config.Datadog.Set("admission_controller.reinvocation_policy", "wrong")
c.config = NewConfig(true, false)
webhook = c.getWebhookSkeleton("foo", "/bar")
assert.Equal(t, admiv1.IfNeededReinvocationPolicy, *webhook.ReinvocationPolicy)

config.Datadog.Set("admission_controller.reinvocation_policy", "")
c.config = NewConfig(true, false)
webhook = c.getWebhookSkeleton("foo", "/bar")
assert.Equal(t, admiv1.IfNeededReinvocationPolicy, *webhook.ReinvocationPolicy)
}
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ func (c *ControllerV1beta1) getWebhookSkeleton(nameSuffix, path string) admiv1be
port := c.config.getServicePort()
timeout := c.config.getTimeout()
failurePolicy := c.getAdmiV1Beta1FailurePolicy()
reinvocationPolicy := c.getReinvocationPolicy()
webhook := admiv1beta1.MutatingWebhook{
Name: c.config.configName(nameSuffix),
ClientConfig: admiv1beta1.WebhookClientConfig{
Expand All @@ -226,6 +227,7 @@ func (c *ControllerV1beta1) getWebhookSkeleton(nameSuffix, path string) admiv1be
},
},
},
ReinvocationPolicy: &reinvocationPolicy,
FailurePolicy: &failurePolicy,
MatchPolicy: &matchPolicy,
SideEffects: &sideEffects,
Expand Down Expand Up @@ -256,3 +258,16 @@ func (c *ControllerV1beta1) getAdmiV1Beta1FailurePolicy() admiv1beta1.FailurePol
return admiv1beta1.Ignore
}
}

func (c *ControllerV1beta1) getReinvocationPolicy() admiv1beta1.ReinvocationPolicyType {
policy := strings.ToLower(c.config.getReinvocationPolicy())
switch policy {
case "ifneeded":
return admiv1beta1.IfNeededReinvocationPolicy
case "never":
return admiv1beta1.NeverReinvocationPolicy
default:
log.Warnf("Unknown reinvocation policy %q - defaulting to %q", policy, admiv1beta1.IfNeededReinvocationPolicy)
return admiv1beta1.IfNeededReinvocationPolicy
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ func TestAdmissionControllerFailureModeFailV1beta1(t *testing.T) {

func TestGenerateTemplatesV1beta1(t *testing.T) {
mockConfig := config.Mock()
defaultReinvocationPolicy := admiv1beta1.IfNeededReinvocationPolicy
failurePolicy := admiv1beta1.Ignore
matchPolicy := admiv1beta1.Exact
sideEffects := admiv1beta1.SideEffectClassNone
Expand Down Expand Up @@ -202,6 +203,7 @@ func TestGenerateTemplatesV1beta1(t *testing.T) {
},
},
},
ReinvocationPolicy: &defaultReinvocationPolicy,
FailurePolicy: &failurePolicy,
MatchPolicy: &matchPolicy,
SideEffects: &sideEffects,
Expand Down Expand Up @@ -385,6 +387,7 @@ func TestGetWebhookSkeletonV1beta1(t *testing.T) {
failurePolicy := admiv1beta1.Ignore
matchPolicy := admiv1beta1.Exact
sideEffects := admiv1beta1.SideEffectClassNone
defaultReinvocationPolicy := admiv1beta1.IfNeededReinvocationPolicy
port := int32(443)
path := "/bar"
defaultTimeout := config.Datadog.GetInt32("admission_controller.timeout_seconds")
Expand Down Expand Up @@ -412,6 +415,7 @@ func TestGetWebhookSkeletonV1beta1(t *testing.T) {
},
},
},
ReinvocationPolicy: &defaultReinvocationPolicy,
FailurePolicy: &failurePolicy,
MatchPolicy: &matchPolicy,
SideEffects: &sideEffects,
Expand Down Expand Up @@ -526,3 +530,42 @@ func validateV1beta1(w *admiv1beta1.MutatingWebhookConfiguration, s *corev1.Secr
}
return nil
}

func TestAdmissionControllerReinvocationPolicyV1beta1(t *testing.T) {
f := newFixtureV1beta1(t)
c := f.run(t)
c.config = NewConfig(true, false)

defaultValue := config.Datadog.Get("admission_controller.reinvocation_policy")
defer config.Datadog.Set("admission_controller.reinvocation_policy", defaultValue)

config.Datadog.Set("admission_controller.reinvocation_policy", "IfNeeded")
c.config = NewConfig(true, false)
webhook := c.getWebhookSkeleton("foo", "/bar")
assert.Equal(t, admiv1beta1.IfNeededReinvocationPolicy, *webhook.ReinvocationPolicy)

config.Datadog.Set("admission_controller.reinvocation_policy", "ifneeded")
c.config = NewConfig(true, false)
webhook = c.getWebhookSkeleton("foo", "/bar")
assert.Equal(t, admiv1beta1.IfNeededReinvocationPolicy, *webhook.ReinvocationPolicy)

config.Datadog.Set("admission_controller.reinvocation_policy", "Never")
c.config = NewConfig(true, false)
webhook = c.getWebhookSkeleton("foo", "/bar")
assert.Equal(t, admiv1beta1.NeverReinvocationPolicy, *webhook.ReinvocationPolicy)

config.Datadog.Set("admission_controller.reinvocation_policy", "never")
c.config = NewConfig(true, false)
webhook = c.getWebhookSkeleton("foo", "/bar")
assert.Equal(t, admiv1beta1.NeverReinvocationPolicy, *webhook.ReinvocationPolicy)

config.Datadog.Set("admission_controller.reinvocation_policy", "wrong")
c.config = NewConfig(true, false)
webhook = c.getWebhookSkeleton("foo", "/bar")
assert.Equal(t, admiv1beta1.IfNeededReinvocationPolicy, *webhook.ReinvocationPolicy)

config.Datadog.Set("admission_controller.reinvocation_policy", "")
c.config = NewConfig(true, false)
webhook = c.getWebhookSkeleton("foo", "/bar")
assert.Equal(t, admiv1beta1.IfNeededReinvocationPolicy, *webhook.ReinvocationPolicy)
}
1 change: 1 addition & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,7 @@ func InitConfig(config Config) {
config.BindEnvAndSetDefault("admission_controller.pod_owners_cache_validity", 10) // in minutes
config.BindEnvAndSetDefault("admission_controller.namespace_selector_fallback", false)
config.BindEnvAndSetDefault("admission_controller.failure_policy", "Ignore")
config.BindEnvAndSetDefault("admission_controller.reinvocation_policy", "IfNeeded")

// Telemetry
// Enable telemetry metrics on the internals of the Agent.
Expand Down
7 changes: 7 additions & 0 deletions pkg/config/config_template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2441,6 +2441,13 @@ api_key:
## Setting to Fail will require the admission controller to be present and pods to be injected before they are allowed to run.
#
# failure_policy: Ignore

## @param reinvocation_policy - string - optional - default: IfNeeded
## @env DD_ADMISSION_CONTROLLER_REINVOCATION_POLICY - string - optional - default: IfNeeded
## Set the reinvocation policy for dynamic admission control.
## See https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#reinvocation-policy
#
# reinvocation_policy: IfNeeded
{{ end -}}
{{- if .DockerTagging }}

Expand Down
5 changes: 5 additions & 0 deletions releasenotes-dca/notes/adm-reinvocation-e1435102b435f1d1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
enhancements:
- |
The admission controller's reinvocation policy is now set to ``IfNeeded`` by default.
It can be changed using the ``admission_controller.reinvocation_policy`` parameter.

0 comments on commit 01a5330

Please sign in to comment.