mirror of https://github.com/knative/pkg.git
Make the fields of the AdmissionController public. (#24)
This commit is contained in:
parent
4d4c00734e
commit
03fb14296d
|
@ -107,11 +107,11 @@ type ResourceDefaulter func(patches *[]jsonpatch.JsonPatchOperation, crd Generic
|
||||||
// AdmissionController implements the external admission webhook for validation of
|
// AdmissionController implements the external admission webhook for validation of
|
||||||
// pilot configuration.
|
// pilot configuration.
|
||||||
type AdmissionController struct {
|
type AdmissionController struct {
|
||||||
client kubernetes.Interface
|
Client kubernetes.Interface
|
||||||
options ControllerOptions
|
Options ControllerOptions
|
||||||
groupVersion schema.GroupVersion
|
GroupVersion schema.GroupVersion
|
||||||
handlers map[string]runtime.Object
|
Handlers map[string]runtime.Object
|
||||||
logger *zap.SugaredLogger
|
Logger *zap.SugaredLogger
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenericCRD is the interface definition that allows us to perform the generic
|
// GenericCRD is the interface definition that allows us to perform the generic
|
||||||
|
@ -268,9 +268,9 @@ func configureCerts(ctx context.Context, client kubernetes.Interface, options *C
|
||||||
|
|
||||||
// Run implements the admission controller run loop.
|
// Run implements the admission controller run loop.
|
||||||
func (ac *AdmissionController) Run(stop <-chan struct{}) error {
|
func (ac *AdmissionController) Run(stop <-chan struct{}) error {
|
||||||
logger := ac.logger
|
logger := ac.Logger
|
||||||
ctx := logging.WithLogger(context.TODO(), logger)
|
ctx := logging.WithLogger(context.TODO(), logger)
|
||||||
tlsConfig, caCert, err := configureCerts(ctx, ac.client, &ac.options)
|
tlsConfig, caCert, err := configureCerts(ctx, ac.Client, &ac.Options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Could not configure admission webhook certs", zap.Error(err))
|
logger.Error("Could not configure admission webhook certs", zap.Error(err))
|
||||||
return err
|
return err
|
||||||
|
@ -278,18 +278,18 @@ func (ac *AdmissionController) Run(stop <-chan struct{}) error {
|
||||||
|
|
||||||
server := &http.Server{
|
server := &http.Server{
|
||||||
Handler: ac,
|
Handler: ac,
|
||||||
Addr: fmt.Sprintf(":%v", ac.options.Port),
|
Addr: fmt.Sprintf(":%v", ac.Options.Port),
|
||||||
TLSConfig: tlsConfig,
|
TLSConfig: tlsConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("Found certificates for webhook...")
|
logger.Info("Found certificates for webhook...")
|
||||||
if ac.options.RegistrationDelay != 0 {
|
if ac.Options.RegistrationDelay != 0 {
|
||||||
logger.Infof("Delaying admission webhook registration for %v", ac.options.RegistrationDelay)
|
logger.Infof("Delaying admission webhook registration for %v", ac.Options.RegistrationDelay)
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-time.After(ac.options.RegistrationDelay):
|
case <-time.After(ac.Options.RegistrationDelay):
|
||||||
cl := ac.client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations()
|
cl := ac.Client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations()
|
||||||
if err := ac.register(ctx, cl, caCert); err != nil {
|
if err := ac.register(ctx, cl, caCert); err != nil {
|
||||||
logger.Error("Failed to register webhook", zap.Error(err))
|
logger.Error("Failed to register webhook", zap.Error(err))
|
||||||
return err
|
return err
|
||||||
|
@ -330,7 +330,7 @@ func (ac *AdmissionController) register(
|
||||||
failurePolicy := admissionregistrationv1beta1.Fail
|
failurePolicy := admissionregistrationv1beta1.Fail
|
||||||
|
|
||||||
resources := sort.StringSlice{}
|
resources := sort.StringSlice{}
|
||||||
for k := range ac.handlers {
|
for k := range ac.Handlers {
|
||||||
// Lousy pluralizer
|
// Lousy pluralizer
|
||||||
resources = append(resources, strings.ToLower(k)+"s")
|
resources = append(resources, strings.ToLower(k)+"s")
|
||||||
}
|
}
|
||||||
|
@ -338,25 +338,25 @@ func (ac *AdmissionController) register(
|
||||||
|
|
||||||
webhook := &admissionregistrationv1beta1.MutatingWebhookConfiguration{
|
webhook := &admissionregistrationv1beta1.MutatingWebhookConfiguration{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: ac.options.WebhookName,
|
Name: ac.Options.WebhookName,
|
||||||
},
|
},
|
||||||
Webhooks: []admissionregistrationv1beta1.Webhook{{
|
Webhooks: []admissionregistrationv1beta1.Webhook{{
|
||||||
Name: ac.options.WebhookName,
|
Name: ac.Options.WebhookName,
|
||||||
Rules: []admissionregistrationv1beta1.RuleWithOperations{{
|
Rules: []admissionregistrationv1beta1.RuleWithOperations{{
|
||||||
Operations: []admissionregistrationv1beta1.OperationType{
|
Operations: []admissionregistrationv1beta1.OperationType{
|
||||||
admissionregistrationv1beta1.Create,
|
admissionregistrationv1beta1.Create,
|
||||||
admissionregistrationv1beta1.Update,
|
admissionregistrationv1beta1.Update,
|
||||||
},
|
},
|
||||||
Rule: admissionregistrationv1beta1.Rule{
|
Rule: admissionregistrationv1beta1.Rule{
|
||||||
APIGroups: []string{ac.groupVersion.Group},
|
APIGroups: []string{ac.GroupVersion.Group},
|
||||||
APIVersions: []string{ac.groupVersion.Version},
|
APIVersions: []string{ac.GroupVersion.Version},
|
||||||
Resources: resources,
|
Resources: resources,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
ClientConfig: admissionregistrationv1beta1.WebhookClientConfig{
|
ClientConfig: admissionregistrationv1beta1.WebhookClientConfig{
|
||||||
Service: &admissionregistrationv1beta1.ServiceReference{
|
Service: &admissionregistrationv1beta1.ServiceReference{
|
||||||
Namespace: ac.options.Namespace,
|
Namespace: ac.Options.Namespace,
|
||||||
Name: ac.options.ServiceName,
|
Name: ac.Options.ServiceName,
|
||||||
},
|
},
|
||||||
CABundle: caCert,
|
CABundle: caCert,
|
||||||
},
|
},
|
||||||
|
@ -365,7 +365,7 @@ func (ac *AdmissionController) register(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the owner to our deployment
|
// Set the owner to our deployment
|
||||||
deployment, err := ac.client.ExtensionsV1beta1().Deployments(ac.options.Namespace).Get(ac.options.DeploymentName, metav1.GetOptions{})
|
deployment, err := ac.Client.ExtensionsV1beta1().Deployments(ac.Options.Namespace).Get(ac.Options.DeploymentName, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to fetch our deployment: %s", err)
|
return fmt.Errorf("Failed to fetch our deployment: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -379,7 +379,7 @@ func (ac *AdmissionController) register(
|
||||||
return fmt.Errorf("Failed to create a webhook: %s", err)
|
return fmt.Errorf("Failed to create a webhook: %s", err)
|
||||||
}
|
}
|
||||||
logger.Info("Webhook already exists")
|
logger.Info("Webhook already exists")
|
||||||
configuredWebhook, err := client.Get(ac.options.WebhookName, metav1.GetOptions{})
|
configuredWebhook, err := client.Get(ac.Options.WebhookName, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error retrieving webhook: %s", err)
|
return fmt.Errorf("Error retrieving webhook: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -402,7 +402,7 @@ func (ac *AdmissionController) register(
|
||||||
// ServeHTTP implements the external admission webhook for mutating
|
// ServeHTTP implements the external admission webhook for mutating
|
||||||
// serving resources.
|
// serving resources.
|
||||||
func (ac *AdmissionController) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (ac *AdmissionController) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
logger := ac.logger
|
logger := ac.Logger
|
||||||
logger.Infof("Webhook ServeHTTP request=%#v", r)
|
logger.Infof("Webhook ServeHTTP request=%#v", r)
|
||||||
|
|
||||||
// verify the content type is accurate
|
// verify the content type is accurate
|
||||||
|
@ -478,7 +478,7 @@ func (ac *AdmissionController) admit(ctx context.Context, request *admissionv1be
|
||||||
|
|
||||||
func (ac *AdmissionController) mutate(ctx context.Context, kind string, oldBytes []byte, newBytes []byte) ([]byte, error) {
|
func (ac *AdmissionController) mutate(ctx context.Context, kind string, oldBytes []byte, newBytes []byte) ([]byte, error) {
|
||||||
logger := logging.FromContext(ctx)
|
logger := logging.FromContext(ctx)
|
||||||
handler, ok := ac.handlers[kind]
|
handler, ok := ac.Handlers[kind]
|
||||||
if !ok {
|
if !ok {
|
||||||
logger.Errorf("Unhandled kind %q", kind)
|
logger.Errorf("Unhandled kind %q", kind)
|
||||||
return nil, fmt.Errorf("unhandled kind: %q", kind)
|
return nil, fmt.Errorf("unhandled kind: %q", kind)
|
||||||
|
|
|
@ -54,7 +54,7 @@ func TestMissingContentType(t *testing.T) {
|
||||||
t.Fatalf("waitForServerAvailable() = %v", err)
|
t.Fatalf("waitForServerAvailable() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tlsClient, err := createSecureTLSClient(t, ac.client, &ac.options)
|
tlsClient, err := createSecureTLSClient(t, ac.Client, &ac.Options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("createSecureTLSClient() = %v", err)
|
t.Fatalf("createSecureTLSClient() = %v", err)
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ func TestEmptyRequestBody(t *testing.T) {
|
||||||
t.Fatalf("waitForServerAvailable() = %v", err)
|
t.Fatalf("waitForServerAvailable() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tlsClient, err := createSecureTLSClient(t, ac.client, &ac.options)
|
tlsClient, err := createSecureTLSClient(t, ac.Client, &ac.Options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("createSecureTLSClient() = %v", err)
|
t.Fatalf("createSecureTLSClient() = %v", err)
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ func TestValidResponseForResource(t *testing.T) {
|
||||||
if pollErr != nil {
|
if pollErr != nil {
|
||||||
t.Fatalf("waitForServerAvailable() = %v", err)
|
t.Fatalf("waitForServerAvailable() = %v", err)
|
||||||
}
|
}
|
||||||
tlsClient, err := createSecureTLSClient(t, ac.client, &ac.options)
|
tlsClient, err := createSecureTLSClient(t, ac.Client, &ac.Options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("createSecureTLSClient() = %v", err)
|
t.Fatalf("createSecureTLSClient() = %v", err)
|
||||||
}
|
}
|
||||||
|
@ -248,7 +248,7 @@ func TestInvalidResponseForResource(t *testing.T) {
|
||||||
if pollErr != nil {
|
if pollErr != nil {
|
||||||
t.Fatalf("waitForServerAvailable() = %v", err)
|
t.Fatalf("waitForServerAvailable() = %v", err)
|
||||||
}
|
}
|
||||||
tlsClient, err := createSecureTLSClient(t, ac.client, &ac.options)
|
tlsClient, err := createSecureTLSClient(t, ac.Client, &ac.Options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("createSecureTLSClient() = %v", err)
|
t.Fatalf("createSecureTLSClient() = %v", err)
|
||||||
}
|
}
|
||||||
|
@ -335,12 +335,12 @@ func testSetup(t *testing.T) (*AdmissionController, string, error) {
|
||||||
defaultOpts.Port = port
|
defaultOpts.Port = port
|
||||||
_, ac := newNonRunningTestAdmissionController(t, defaultOpts)
|
_, ac := newNonRunningTestAdmissionController(t, defaultOpts)
|
||||||
|
|
||||||
nsErr := createNamespace(t, ac.client, metav1.NamespaceSystem)
|
nsErr := createNamespace(t, ac.Client, metav1.NamespaceSystem)
|
||||||
if nsErr != nil {
|
if nsErr != nil {
|
||||||
return nil, "", nsErr
|
return nil, "", nsErr
|
||||||
}
|
}
|
||||||
|
|
||||||
cMapsErr := createTestConfigMap(t, ac.client)
|
cMapsErr := createTestConfigMap(t, ac.Client)
|
||||||
if cMapsErr != nil {
|
if cMapsErr != nil {
|
||||||
return nil, "", cMapsErr
|
return nil, "", cMapsErr
|
||||||
}
|
}
|
||||||
|
|
|
@ -249,8 +249,8 @@ func TestInvalidUpdateResourceFailsImmutability(t *testing.T) {
|
||||||
func TestValidWebhook(t *testing.T) {
|
func TestValidWebhook(t *testing.T) {
|
||||||
_, ac := newNonRunningTestAdmissionController(t, newDefaultOptions())
|
_, ac := newNonRunningTestAdmissionController(t, newDefaultOptions())
|
||||||
createDeployment(ac)
|
createDeployment(ac)
|
||||||
ac.register(TestContextWithLogger(t), ac.client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations(), []byte{})
|
ac.register(TestContextWithLogger(t), ac.Client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations(), []byte{})
|
||||||
_, err := ac.client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Get(ac.options.WebhookName, metav1.GetOptions{})
|
_, err := ac.Client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Get(ac.Options.WebhookName, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create webhook: %s", err)
|
t.Fatalf("Failed to create webhook: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -260,10 +260,10 @@ func TestUpdatingWebhook(t *testing.T) {
|
||||||
_, ac := newNonRunningTestAdmissionController(t, newDefaultOptions())
|
_, ac := newNonRunningTestAdmissionController(t, newDefaultOptions())
|
||||||
webhook := &admissionregistrationv1beta1.MutatingWebhookConfiguration{
|
webhook := &admissionregistrationv1beta1.MutatingWebhookConfiguration{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: ac.options.WebhookName,
|
Name: ac.Options.WebhookName,
|
||||||
},
|
},
|
||||||
Webhooks: []admissionregistrationv1beta1.Webhook{{
|
Webhooks: []admissionregistrationv1beta1.Webhook{{
|
||||||
Name: ac.options.WebhookName,
|
Name: ac.Options.WebhookName,
|
||||||
Rules: []admissionregistrationv1beta1.RuleWithOperations{{}},
|
Rules: []admissionregistrationv1beta1.RuleWithOperations{{}},
|
||||||
ClientConfig: admissionregistrationv1beta1.WebhookClientConfig{},
|
ClientConfig: admissionregistrationv1beta1.WebhookClientConfig{},
|
||||||
}},
|
}},
|
||||||
|
@ -271,8 +271,8 @@ func TestUpdatingWebhook(t *testing.T) {
|
||||||
|
|
||||||
createDeployment(ac)
|
createDeployment(ac)
|
||||||
createWebhook(ac, webhook)
|
createWebhook(ac, webhook)
|
||||||
ac.register(TestContextWithLogger(t), ac.client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations(), []byte{})
|
ac.register(TestContextWithLogger(t), ac.Client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations(), []byte{})
|
||||||
currentWebhook, _ := ac.client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Get(ac.options.WebhookName, metav1.GetOptions{})
|
currentWebhook, _ := ac.Client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Get(ac.Options.WebhookName, metav1.GetOptions{})
|
||||||
if reflect.DeepEqual(currentWebhook.Webhooks, webhook.Webhooks) {
|
if reflect.DeepEqual(currentWebhook.Webhooks, webhook.Webhooks) {
|
||||||
t.Fatalf("Expected webhook to be updated")
|
t.Fatalf("Expected webhook to be updated")
|
||||||
}
|
}
|
||||||
|
@ -282,11 +282,11 @@ func TestRegistrationForAlreadyExistingWebhook(t *testing.T) {
|
||||||
_, ac := newNonRunningTestAdmissionController(t, newDefaultOptions())
|
_, ac := newNonRunningTestAdmissionController(t, newDefaultOptions())
|
||||||
webhook := &admissionregistrationv1beta1.MutatingWebhookConfiguration{
|
webhook := &admissionregistrationv1beta1.MutatingWebhookConfiguration{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: ac.options.WebhookName,
|
Name: ac.Options.WebhookName,
|
||||||
},
|
},
|
||||||
Webhooks: []admissionregistrationv1beta1.Webhook{
|
Webhooks: []admissionregistrationv1beta1.Webhook{
|
||||||
{
|
{
|
||||||
Name: ac.options.WebhookName,
|
Name: ac.Options.WebhookName,
|
||||||
Rules: []admissionregistrationv1beta1.RuleWithOperations{{}},
|
Rules: []admissionregistrationv1beta1.RuleWithOperations{{}},
|
||||||
ClientConfig: admissionregistrationv1beta1.WebhookClientConfig{},
|
ClientConfig: admissionregistrationv1beta1.WebhookClientConfig{},
|
||||||
},
|
},
|
||||||
|
@ -294,7 +294,7 @@ func TestRegistrationForAlreadyExistingWebhook(t *testing.T) {
|
||||||
}
|
}
|
||||||
createWebhook(ac, webhook)
|
createWebhook(ac, webhook)
|
||||||
|
|
||||||
ac.options.RegistrationDelay = 1 * time.Millisecond
|
ac.Options.RegistrationDelay = 1 * time.Millisecond
|
||||||
stopCh := make(chan struct{})
|
stopCh := make(chan struct{})
|
||||||
errCh := make(chan error)
|
errCh := make(chan error)
|
||||||
|
|
||||||
|
@ -330,10 +330,10 @@ func TestCertConfigurationForAlreadyGeneratedSecret(t *testing.T) {
|
||||||
t.Fatalf("Failed to create secret: %v", err)
|
t.Fatalf("Failed to create secret: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
createNamespace(t, ac.client, metav1.NamespaceSystem)
|
createNamespace(t, ac.Client, metav1.NamespaceSystem)
|
||||||
createTestConfigMap(t, ac.client)
|
createTestConfigMap(t, ac.Client)
|
||||||
|
|
||||||
tlsConfig, caCert, err := configureCerts(ctx, kubeClient, &ac.options)
|
tlsConfig, caCert, err := configureCerts(ctx, kubeClient, &ac.Options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to configure secret: %v", err)
|
t.Fatalf("Failed to configure secret: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -366,10 +366,10 @@ func TestCertConfigurationForGeneratedSecret(t *testing.T) {
|
||||||
kubeClient, ac := newNonRunningTestAdmissionController(t, opts)
|
kubeClient, ac := newNonRunningTestAdmissionController(t, opts)
|
||||||
|
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
createNamespace(t, ac.client, metav1.NamespaceSystem)
|
createNamespace(t, ac.Client, metav1.NamespaceSystem)
|
||||||
createTestConfigMap(t, ac.client)
|
createTestConfigMap(t, ac.Client)
|
||||||
|
|
||||||
tlsConfig, caCert, err := configureCerts(ctx, kubeClient, &ac.options)
|
tlsConfig, caCert, err := configureCerts(ctx, kubeClient, &ac.Options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to configure certificates: %v", err)
|
t.Fatalf("Failed to configure certificates: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -397,7 +397,7 @@ func createDeployment(ac *AdmissionController) {
|
||||||
Namespace: "knative-something",
|
Namespace: "knative-something",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
ac.client.ExtensionsV1beta1().Deployments("knative-something").Create(deployment)
|
ac.Client.ExtensionsV1beta1().Deployments("knative-something").Create(deployment)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createResource(generation int64, name string) Resource {
|
func createResource(generation int64, name string) Resource {
|
||||||
|
@ -449,7 +449,7 @@ func createCreateResource(r *Resource) *admissionv1beta1.AdmissionRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
func createWebhook(ac *AdmissionController, webhook *admissionregistrationv1beta1.MutatingWebhookConfiguration) {
|
func createWebhook(ac *AdmissionController, webhook *admissionregistrationv1beta1.MutatingWebhookConfiguration) {
|
||||||
client := ac.client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations()
|
client := ac.Client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations()
|
||||||
_, err := client.Create(webhook)
|
_, err := client.Create(webhook)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("failed to create test webhook: %s", err))
|
panic(fmt.Sprintf("failed to create test webhook: %s", err))
|
||||||
|
@ -500,15 +500,15 @@ func incrementGenerationPatch(old float64) jsonpatch.JsonPatchOperation {
|
||||||
func NewAdmissionController(client kubernetes.Interface, options ControllerOptions,
|
func NewAdmissionController(client kubernetes.Interface, options ControllerOptions,
|
||||||
logger *zap.SugaredLogger) (*AdmissionController, error) {
|
logger *zap.SugaredLogger) (*AdmissionController, error) {
|
||||||
return &AdmissionController{
|
return &AdmissionController{
|
||||||
client: client,
|
Client: client,
|
||||||
options: options,
|
Options: options,
|
||||||
groupVersion: schema.GroupVersion{
|
GroupVersion: schema.GroupVersion{
|
||||||
Group: "pkg.knative.dev",
|
Group: "pkg.knative.dev",
|
||||||
Version: "v1alpha1",
|
Version: "v1alpha1",
|
||||||
},
|
},
|
||||||
handlers: map[string]runtime.Object{
|
Handlers: map[string]runtime.Object{
|
||||||
"Resource": &Resource{},
|
"Resource": &Resource{},
|
||||||
},
|
},
|
||||||
logger: logger,
|
Logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue