255 lines
6.4 KiB
Go
255 lines
6.4 KiB
Go
![]() |
package cmd_test
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"reflect"
|
||
|
"testing"
|
||
|
|
||
|
"github.com/jet/kube-webhook-certgen/cmd"
|
||
|
"github.com/jet/kube-webhook-certgen/pkg/k8s"
|
||
|
)
|
||
|
|
||
|
func Test_Patch(t *testing.T) {
|
||
|
t.Parallel()
|
||
|
|
||
|
ctx := context.TODO()
|
||
|
|
||
|
t.Run("patches_APIService_object_when_requested", func(t *testing.T) {
|
||
|
t.Parallel()
|
||
|
|
||
|
config := testPatchConfig()
|
||
|
config.APIServiceName = "bar"
|
||
|
|
||
|
patcher := testPatcher()
|
||
|
patcher.patchObjects = func(_ context.Context, options k8s.PatchOptions) error {
|
||
|
if options.APIServiceName != config.APIServiceName {
|
||
|
return fmt.Errorf("unexpected APIService name %q, expected %q", options.APIServiceName, config.APIServiceName)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
config.Patcher = patcher
|
||
|
|
||
|
if err := cmd.Patch(ctx, config); err != nil {
|
||
|
t.Fatalf("Unexpected patching error: %v", err)
|
||
|
}
|
||
|
})
|
||
|
|
||
|
t.Run("use_configured_webhook_name_for_patching", func(t *testing.T) {
|
||
|
t.Parallel()
|
||
|
|
||
|
config := testPatchConfig()
|
||
|
config.WebhookName = "foo"
|
||
|
|
||
|
patcher := testPatcher()
|
||
|
patcher.patchObjects = func(_ context.Context, options k8s.PatchOptions) error {
|
||
|
if options.ValidatingWebhookConfigurationName != config.WebhookName {
|
||
|
return fmt.Errorf("unexpected object name %q, expected %q", options.ValidatingWebhookConfigurationName, config.WebhookName)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
config.Patcher = patcher
|
||
|
|
||
|
if err := cmd.Patch(ctx, config); err != nil {
|
||
|
t.Fatalf("Unexpected patching error: %v", err)
|
||
|
}
|
||
|
})
|
||
|
|
||
|
t.Run("patches_only_validating_webhook_when_requested", func(t *testing.T) {
|
||
|
t.Parallel()
|
||
|
|
||
|
config := testPatchConfig()
|
||
|
config.PatchValidating = true
|
||
|
config.PatchMutating = false
|
||
|
|
||
|
patcher := testPatcher()
|
||
|
patcher.patchObjects = func(_ context.Context, options k8s.PatchOptions) error {
|
||
|
if options.ValidatingWebhookConfigurationName == "" {
|
||
|
t.Error("expected validating webhook to be patched")
|
||
|
}
|
||
|
|
||
|
if options.MutatingWebhookConfigurationName != "" {
|
||
|
t.Error("expected mutating webhook to not be patched")
|
||
|
}
|
||
|
|
||
|
if options.APIServiceName != "" {
|
||
|
t.Error("expected APIService to not be patched")
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
config.Patcher = patcher
|
||
|
|
||
|
if err := cmd.Patch(ctx, config); err != nil {
|
||
|
t.Fatalf("Unexpected patching error: %v", err)
|
||
|
}
|
||
|
})
|
||
|
|
||
|
t.Run("patches_both_webhooks_when_requested", func(t *testing.T) {
|
||
|
t.Parallel()
|
||
|
|
||
|
config := testPatchConfig()
|
||
|
config.PatchValidating = true
|
||
|
config.PatchMutating = true
|
||
|
|
||
|
patcher := testPatcher()
|
||
|
patcher.patchObjects = func(_ context.Context, options k8s.PatchOptions) error {
|
||
|
if options.ValidatingWebhookConfigurationName == "" {
|
||
|
t.Error("expected validating webhook to be patched")
|
||
|
}
|
||
|
|
||
|
if options.MutatingWebhookConfigurationName == "" {
|
||
|
t.Error("expected mutating webhook to be patched")
|
||
|
}
|
||
|
|
||
|
if options.APIServiceName != "" {
|
||
|
t.Error("expected APIService to not be patched")
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
config.Patcher = patcher
|
||
|
|
||
|
if err := cmd.Patch(ctx, config); err != nil {
|
||
|
t.Fatalf("Unexpected patching error: %v", err)
|
||
|
}
|
||
|
})
|
||
|
|
||
|
t.Run("use_empty_policy_when_ignore_is_requested", func(t *testing.T) {
|
||
|
t.Parallel()
|
||
|
|
||
|
config := testPatchConfig()
|
||
|
config.PatchFailurePolicy = "Ignore"
|
||
|
|
||
|
patcher := testPatcher()
|
||
|
patcher.patchObjects = func(_ context.Context, options k8s.PatchOptions) error {
|
||
|
if options.FailurePolicyType != "" {
|
||
|
return fmt.Errorf("expected policy to be nil. got: %q", options.FailurePolicyType)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
config.Patcher = patcher
|
||
|
|
||
|
if err := cmd.Patch(ctx, config); err != nil {
|
||
|
t.Fatalf("Unexpected patching error: %v", err)
|
||
|
}
|
||
|
})
|
||
|
|
||
|
t.Run("use_fail_policy_when_fail_is_requested", func(t *testing.T) {
|
||
|
t.Parallel()
|
||
|
|
||
|
config := testPatchConfig()
|
||
|
config.PatchFailurePolicy = "Fail"
|
||
|
|
||
|
patcher := testPatcher()
|
||
|
patcher.patchObjects = func(_ context.Context, options k8s.PatchOptions) error {
|
||
|
if options.FailurePolicyType == "" || options.FailurePolicyType != "Fail" {
|
||
|
return fmt.Errorf("unexpected policy: %q", options.FailurePolicyType)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
config.Patcher = patcher
|
||
|
|
||
|
if err := cmd.Patch(ctx, config); err != nil {
|
||
|
t.Fatalf("Unexpected patching error: %v", err)
|
||
|
}
|
||
|
})
|
||
|
|
||
|
t.Run("use_obtained_ca_certificate_for_patching", func(t *testing.T) {
|
||
|
t.Parallel()
|
||
|
|
||
|
expectedCA := []byte("foo")
|
||
|
|
||
|
config := testPatchConfig()
|
||
|
|
||
|
patcher := testPatcher()
|
||
|
patcher.patchObjects = func(_ context.Context, options k8s.PatchOptions) error {
|
||
|
if !reflect.DeepEqual(options.CABundle, expectedCA) {
|
||
|
return fmt.Errorf("unexpected CA, expected %q, got %q", string(expectedCA), string(options.CABundle))
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
patcher.getCaFromSecret = func(context.Context, string, string) []byte {
|
||
|
return expectedCA
|
||
|
}
|
||
|
config.Patcher = patcher
|
||
|
|
||
|
if err := cmd.Patch(ctx, config); err != nil {
|
||
|
t.Fatalf("Unexpected patching error: %v", err)
|
||
|
}
|
||
|
})
|
||
|
|
||
|
t.Run("returns_error_when", func(t *testing.T) {
|
||
|
t.Parallel()
|
||
|
|
||
|
for name, mutateF := range map[string]func(*cmd.PatchConfig){
|
||
|
"no_patcher_is_defined": func(c *cmd.PatchConfig) {
|
||
|
c.Patcher = nil
|
||
|
},
|
||
|
"no_webhooks_are_requested_for_patching": func(c *cmd.PatchConfig) {
|
||
|
c.PatchValidating = false
|
||
|
c.PatchMutating = false
|
||
|
c.APIServiceName = ""
|
||
|
},
|
||
|
"unsupported_patch_failure_policy_is_defined": func(c *cmd.PatchConfig) {
|
||
|
c.PatchFailurePolicy = "foo"
|
||
|
},
|
||
|
"ca_certificate_from_secret_is_empty": func(c *cmd.PatchConfig) {
|
||
|
patcher := testPatcher()
|
||
|
patcher.getCaFromSecret = func(_ context.Context, _, _ string) []byte {
|
||
|
return nil
|
||
|
}
|
||
|
c.Patcher = patcher
|
||
|
},
|
||
|
} {
|
||
|
mutateF := mutateF
|
||
|
|
||
|
t.Run(name, func(t *testing.T) {
|
||
|
t.Parallel()
|
||
|
|
||
|
config := testPatchConfig()
|
||
|
mutateF(config)
|
||
|
|
||
|
if err := cmd.Patch(ctx, config); err == nil {
|
||
|
t.Fatalf("Expected error while patching")
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
type patcher struct {
|
||
|
patchObjects func(context.Context, k8s.PatchOptions) error
|
||
|
getCaFromSecret func(context.Context, string, string) []byte
|
||
|
}
|
||
|
|
||
|
func (p *patcher) PatchObjects(ctx context.Context, options k8s.PatchOptions) error {
|
||
|
return p.patchObjects(ctx, options)
|
||
|
}
|
||
|
|
||
|
func (p *patcher) GetCaFromSecret(ctx context.Context, secretName, namespace string) []byte {
|
||
|
return p.getCaFromSecret(ctx, secretName, namespace)
|
||
|
}
|
||
|
|
||
|
func testPatcher() *patcher {
|
||
|
return &patcher{
|
||
|
patchObjects: func(context.Context, k8s.PatchOptions) error {
|
||
|
return nil
|
||
|
},
|
||
|
getCaFromSecret: func(context.Context, string, string) []byte { return []byte{} },
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func testPatchConfig() *cmd.PatchConfig {
|
||
|
return &cmd.PatchConfig{
|
||
|
PatchValidating: true,
|
||
|
WebhookName: "foo",
|
||
|
Patcher: testPatcher(),
|
||
|
}
|
||
|
}
|