mirror of https://github.com/knative/caching.git
Auto-update dependencies (#121)
Produced via: `dep ensure -update knative.dev/test-infra knative.dev/pkg` /assign mattmoor
This commit is contained in:
parent
9075f22c2a
commit
ab9eaf9151
|
@ -933,7 +933,7 @@
|
|||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:70af147aaa464fa6248d55e038e1db0d7c70ff6a7a2226c33b5f0d6bf820193b"
|
||||
digest = "1:d91a27f79bca7f71b57bdc3581542d646c90dca75862c38d21ad7b1aca6c22aa"
|
||||
name = "knative.dev/pkg"
|
||||
packages = [
|
||||
"apis",
|
||||
|
@ -952,7 +952,7 @@
|
|||
"metrics/metricskey",
|
||||
]
|
||||
pruneopts = "T"
|
||||
revision = "f684a1078ac309f4b32e6240d9b622bea092296e"
|
||||
revision = "cad41c40ccb5a40de7a3b65097649703c8d96e0b"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
@ -963,7 +963,7 @@
|
|||
"tools/dep-collector",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "385c6ecc17489d72a2e0927d4552bcdc1f0d08e0"
|
||||
revision = "75f9d5135b8f823b6a663fe49f00dbc498b6ad33"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:8730e0150dfb2b7e173890c8b9868e7a273082ef8e39f4940e3506a481cf895c"
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
# Duck Types
|
||||
|
||||
Knative leverages duck-typing to interact with resources inside of Kubernetes
|
||||
without explicit knowlage of the full resource shape. `knative/pkg` defines two
|
||||
duck types that are used throughout Knative: `Addressable` and `Source`.
|
||||
|
||||
For APIs leveraging `ObjectReference`, the context of the resource in question
|
||||
identifies the duck-type. To enable the case where no `ObjectRefrence` is used,
|
||||
we have labeled the Custom Resource Definition with the duck-type. Those labels
|
||||
are as follows:
|
||||
|
||||
| Label | Duck-Type |
|
||||
| ----------------------------------- | ----------------------------------------------------------------------------- |
|
||||
| `duck.knative.dev/addressable=true` | [Addressable](https://godoc.org/knative.dev/pkg/apis/duck/v1#AddressableType) |
|
||||
| `duck.knative.dev/source=true` | [Source](https://godoc.org/knative.dev/pkg/apis/duck/v1#Source) |
|
||||
|
||||
## Addressable Shape
|
||||
|
||||
Addressable is expected to be the following shape:
|
||||
|
||||
```yaml
|
||||
apiVersion: group/version
|
||||
kind: Kind
|
||||
status:
|
||||
address:
|
||||
url: http://host/path?query
|
||||
```
|
||||
|
||||
## Source Shape
|
||||
|
||||
Source is expected to be in the following shape:
|
||||
|
||||
(with ref sink)
|
||||
|
||||
```yaml
|
||||
apiVersion: group/version
|
||||
kind: Kind
|
||||
spec:
|
||||
sink:
|
||||
ref:
|
||||
apiVersion: group/version
|
||||
kind: AnAddressableKind
|
||||
name: a-name
|
||||
ceOverrides:
|
||||
extensions:
|
||||
key: value
|
||||
status:
|
||||
observedGeneration: 1
|
||||
conditions:
|
||||
- type: Ready
|
||||
status: "True"
|
||||
sinkUri: http://host
|
||||
```
|
||||
|
||||
(with uri sink)
|
||||
|
||||
```yaml
|
||||
apiVersion: group/version
|
||||
kind: Kind
|
||||
spec:
|
||||
sink:
|
||||
uri: http://host/path?query
|
||||
ceOverrides:
|
||||
extensions:
|
||||
key: value
|
||||
status:
|
||||
observedGeneration: 1
|
||||
conditions:
|
||||
- type: Ready
|
||||
status: "True"
|
||||
sinkUri: http://host/path?query
|
||||
```
|
||||
|
||||
(with ref and uri sink)
|
||||
|
||||
```yaml
|
||||
apiVersion: group/version
|
||||
kind: Kind
|
||||
spec:
|
||||
sink:
|
||||
ref:
|
||||
apiVersion: group/version
|
||||
kind: AnAddressableKind
|
||||
name: a-name
|
||||
uri: /path?query
|
||||
ceOverrides:
|
||||
extensions:
|
||||
key: value
|
||||
status:
|
||||
observedGeneration: 1
|
||||
conditions:
|
||||
- type: Ready
|
||||
status: "True"
|
||||
sinkUri: http://host/path?query
|
||||
```
|
|
@ -22,13 +22,10 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/markbates/inflect"
|
||||
admissionv1beta1 "k8s.io/api/admission/v1beta1"
|
||||
admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
@ -36,6 +33,7 @@ import (
|
|||
"knative.dev/pkg/configmap"
|
||||
"knative.dev/pkg/kmp"
|
||||
"knative.dev/pkg/logging"
|
||||
"knative.dev/pkg/ptr"
|
||||
)
|
||||
|
||||
// ConfigValidationController implements the AdmissionController for ConfigMaps
|
||||
|
@ -81,84 +79,53 @@ func (ac *ConfigValidationController) Admit(ctx context.Context, request *admiss
|
|||
func (ac *ConfigValidationController) Register(ctx context.Context, kubeClient kubernetes.Interface, caCert []byte) error {
|
||||
client := kubeClient.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations()
|
||||
logger := logging.FromContext(ctx)
|
||||
failurePolicy := admissionregistrationv1beta1.Fail
|
||||
|
||||
resourceGVK := corev1.SchemeGroupVersion.WithKind("ConfigMap")
|
||||
var rules []admissionregistrationv1beta1.RuleWithOperations
|
||||
plural := strings.ToLower(inflect.Pluralize(resourceGVK.Kind))
|
||||
|
||||
ruleScope := admissionregistrationv1beta1.NamespacedScope
|
||||
rules = append(rules, admissionregistrationv1beta1.RuleWithOperations{
|
||||
rules := []admissionregistrationv1beta1.RuleWithOperations{{
|
||||
Operations: []admissionregistrationv1beta1.OperationType{
|
||||
admissionregistrationv1beta1.Create,
|
||||
admissionregistrationv1beta1.Update,
|
||||
},
|
||||
Rule: admissionregistrationv1beta1.Rule{
|
||||
APIGroups: []string{resourceGVK.Group},
|
||||
APIVersions: []string{resourceGVK.Version},
|
||||
Resources: []string{plural + "/*"},
|
||||
APIGroups: []string{""},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"configmaps/*"},
|
||||
Scope: &ruleScope,
|
||||
},
|
||||
})
|
||||
}}
|
||||
|
||||
webhook := &admissionregistrationv1beta1.ValidatingWebhookConfiguration{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: ac.options.ConfigValidationWebhookName,
|
||||
},
|
||||
Webhooks: []admissionregistrationv1beta1.ValidatingWebhook{{
|
||||
Name: ac.options.ConfigValidationWebhookName,
|
||||
Rules: rules,
|
||||
ClientConfig: admissionregistrationv1beta1.WebhookClientConfig{
|
||||
Service: &admissionregistrationv1beta1.ServiceReference{
|
||||
Namespace: ac.options.Namespace,
|
||||
Name: ac.options.ServiceName,
|
||||
Path: &ac.options.ConfigValidationControllerPath,
|
||||
},
|
||||
CABundle: caCert,
|
||||
},
|
||||
NamespaceSelector: &metav1.LabelSelector{
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{{
|
||||
Key: ac.options.ConfigValidationNamespaceLabel,
|
||||
Operator: metav1.LabelSelectorOpExists,
|
||||
}},
|
||||
},
|
||||
FailurePolicy: &failurePolicy,
|
||||
}},
|
||||
configuredWebhook, err := client.Get(ac.options.ConfigValidationWebhookName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error retrieving webhook: %v", err)
|
||||
}
|
||||
|
||||
// Set the owner to our deployment.
|
||||
deployment, err := kubeClient.AppsV1().Deployments(ac.options.Namespace).Get(ac.options.DeploymentName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch our deployment: %v", err)
|
||||
}
|
||||
deploymentRef := metav1.NewControllerRef(deployment, deploymentKind)
|
||||
webhook.OwnerReferences = append(webhook.OwnerReferences, *deploymentRef)
|
||||
webhook := configuredWebhook.DeepCopy()
|
||||
|
||||
// Try to create the webhook and if it already exists validate webhook rules.
|
||||
_, err = client.Create(webhook)
|
||||
if err != nil {
|
||||
if !apierrors.IsAlreadyExists(err) {
|
||||
return fmt.Errorf("failed to create a webhook: %v", err)
|
||||
// Clear out any previous (bad) OwnerReferences.
|
||||
// See: https://github.com/knative/serving/issues/5845
|
||||
webhook.OwnerReferences = nil
|
||||
|
||||
for i, wh := range webhook.Webhooks {
|
||||
if wh.Name != webhook.Name {
|
||||
continue
|
||||
}
|
||||
logger.Info("Webhook already exists")
|
||||
configuredWebhook, err := client.Get(ac.options.ConfigValidationWebhookName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error retrieving webhook: %v", err)
|
||||
webhook.Webhooks[i].Rules = rules
|
||||
webhook.Webhooks[i].ClientConfig.CABundle = caCert
|
||||
if webhook.Webhooks[i].ClientConfig.Service == nil {
|
||||
return fmt.Errorf("missing service reference for webhook: %s", wh.Name)
|
||||
}
|
||||
if ok, err := kmp.SafeEqual(configuredWebhook.Webhooks, webhook.Webhooks); err != nil {
|
||||
return fmt.Errorf("error diffing webhooks: %v", err)
|
||||
} else if !ok {
|
||||
logger.Info("Updating webhook")
|
||||
// Set the ResourceVersion as required by update.
|
||||
webhook.ObjectMeta.ResourceVersion = configuredWebhook.ObjectMeta.ResourceVersion
|
||||
if _, err := client.Update(webhook); err != nil {
|
||||
return fmt.Errorf("failed to update webhook: %s", err)
|
||||
}
|
||||
} else {
|
||||
logger.Info("Webhook is already valid")
|
||||
webhook.Webhooks[i].ClientConfig.Service.Path = ptr.String(ac.options.ConfigValidationControllerPath)
|
||||
}
|
||||
|
||||
if ok, err := kmp.SafeEqual(configuredWebhook, webhook); err != nil {
|
||||
return fmt.Errorf("error diffing webhooks: %v", err)
|
||||
} else if !ok {
|
||||
logger.Info("Updating webhook")
|
||||
if _, err := client.Update(webhook); err != nil {
|
||||
return fmt.Errorf("failed to update webhook: %v", err)
|
||||
}
|
||||
} else {
|
||||
logger.Info("Created a webhook")
|
||||
logger.Info("Webhook is valid")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -32,7 +32,6 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
|
@ -40,6 +39,7 @@ import (
|
|||
"knative.dev/pkg/apis/duck"
|
||||
"knative.dev/pkg/kmp"
|
||||
"knative.dev/pkg/logging"
|
||||
"knative.dev/pkg/ptr"
|
||||
)
|
||||
|
||||
// ResourceCallback defines a signature for resource specific (Route, Configuration, etc.)
|
||||
|
@ -108,7 +108,6 @@ func (ac *ResourceAdmissionController) Admit(ctx context.Context, request *admis
|
|||
func (ac *ResourceAdmissionController) Register(ctx context.Context, kubeClient kubernetes.Interface, caCert []byte) error {
|
||||
client := kubeClient.AdmissionregistrationV1beta1().MutatingWebhookConfigurations()
|
||||
logger := logging.FromContext(ctx)
|
||||
failurePolicy := admissionregistrationv1beta1.Fail
|
||||
|
||||
var rules []admissionregistrationv1beta1.RuleWithOperations
|
||||
for gvk := range ac.handlers {
|
||||
|
@ -139,58 +138,39 @@ func (ac *ResourceAdmissionController) Register(ctx context.Context, kubeClient
|
|||
return lhs.Resources[0] < rhs.Resources[0]
|
||||
})
|
||||
|
||||
webhook := &admissionregistrationv1beta1.MutatingWebhookConfiguration{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: ac.options.ResourceMutatingWebhookName,
|
||||
},
|
||||
Webhooks: []admissionregistrationv1beta1.MutatingWebhook{{
|
||||
Name: ac.options.ResourceMutatingWebhookName,
|
||||
Rules: rules,
|
||||
ClientConfig: admissionregistrationv1beta1.WebhookClientConfig{
|
||||
Service: &admissionregistrationv1beta1.ServiceReference{
|
||||
Namespace: ac.options.Namespace,
|
||||
Name: ac.options.ServiceName,
|
||||
Path: &ac.options.ResourceAdmissionControllerPath,
|
||||
},
|
||||
CABundle: caCert,
|
||||
},
|
||||
FailurePolicy: &failurePolicy,
|
||||
}},
|
||||
configuredWebhook, err := client.Get(ac.options.ResourceMutatingWebhookName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error retrieving webhook: %v", err)
|
||||
}
|
||||
|
||||
// Set the owner to our deployment.
|
||||
deployment, err := kubeClient.AppsV1().Deployments(ac.options.Namespace).Get(ac.options.DeploymentName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch our deployment: %v", err)
|
||||
}
|
||||
deploymentRef := metav1.NewControllerRef(deployment, deploymentKind)
|
||||
webhook.OwnerReferences = append(webhook.OwnerReferences, *deploymentRef)
|
||||
webhook := configuredWebhook.DeepCopy()
|
||||
|
||||
// Try to create the webhook and if it already exists validate webhook rules.
|
||||
_, err = client.Create(webhook)
|
||||
if err != nil {
|
||||
if !apierrors.IsAlreadyExists(err) {
|
||||
return fmt.Errorf("failed to create a webhook: %v", err)
|
||||
// Clear out any previous (bad) OwnerReferences.
|
||||
// See: https://github.com/knative/serving/issues/5845
|
||||
webhook.OwnerReferences = nil
|
||||
|
||||
for i, wh := range webhook.Webhooks {
|
||||
if wh.Name != webhook.Name {
|
||||
continue
|
||||
}
|
||||
logger.Info("Webhook already exists")
|
||||
configuredWebhook, err := client.Get(ac.options.ResourceMutatingWebhookName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error retrieving webhook: %v", err)
|
||||
webhook.Webhooks[i].Rules = rules
|
||||
webhook.Webhooks[i].ClientConfig.CABundle = caCert
|
||||
if webhook.Webhooks[i].ClientConfig.Service == nil {
|
||||
return fmt.Errorf("missing service reference for webhook: %s", wh.Name)
|
||||
}
|
||||
if ok, err := kmp.SafeEqual(configuredWebhook.Webhooks, webhook.Webhooks); err != nil {
|
||||
return fmt.Errorf("error diffing webhooks: %v", err)
|
||||
} else if !ok {
|
||||
logger.Info("Updating webhook")
|
||||
// Set the ResourceVersion as required by update.
|
||||
webhook.ObjectMeta.ResourceVersion = configuredWebhook.ObjectMeta.ResourceVersion
|
||||
if _, err := client.Update(webhook); err != nil {
|
||||
return fmt.Errorf("failed to update webhook: %s", err)
|
||||
}
|
||||
} else {
|
||||
logger.Info("Webhook is already valid")
|
||||
webhook.Webhooks[i].ClientConfig.Service.Path = ptr.String(
|
||||
ac.options.ResourceAdmissionControllerPath)
|
||||
}
|
||||
|
||||
if ok, err := kmp.SafeEqual(configuredWebhook, webhook); err != nil {
|
||||
return fmt.Errorf("error diffing webhooks: %v", err)
|
||||
} else if !ok {
|
||||
logger.Info("Updating webhook")
|
||||
if _, err := client.Update(webhook); err != nil {
|
||||
return fmt.Errorf("failed to update webhook: %v", err)
|
||||
}
|
||||
} else {
|
||||
logger.Info("Created a webhook")
|
||||
logger.Info("Webhook is valid")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -27,12 +27,11 @@ import (
|
|||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
"knative.dev/pkg/logging"
|
||||
"knative.dev/pkg/logging/logkey"
|
||||
|
||||
admissionv1beta1 "k8s.io/api/admission/v1beta1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
@ -46,7 +45,6 @@ const (
|
|||
)
|
||||
|
||||
var (
|
||||
deploymentKind = appsv1.SchemeGroupVersion.WithKind("Deployment")
|
||||
errMissingNewObject = errors.New("the new object may not be nil")
|
||||
)
|
||||
|
||||
|
@ -63,9 +61,6 @@ type ControllerOptions struct {
|
|||
// ServiceName is the service name of the webhook.
|
||||
ServiceName string
|
||||
|
||||
// DeploymentName is the service name of the webhook.
|
||||
DeploymentName string
|
||||
|
||||
// SecretName is the name of k8s secret that contains the webhook
|
||||
// server key/cert and corresponding CA cert that signed them. The
|
||||
// server key/cert are used to serve the webhook and the CA cert
|
||||
|
@ -103,9 +98,6 @@ type ControllerOptions struct {
|
|||
// Service path for ConfigValidationController webhook
|
||||
// Default is "/config-validation" and is set by the constructor
|
||||
ConfigValidationControllerPath string
|
||||
|
||||
// NamespaceLabel is the label for the Namespace we bind ConfigValidationController to
|
||||
ConfigValidationNamespaceLabel string
|
||||
}
|
||||
|
||||
// AdmissionController provides the interface for different admission controllers
|
||||
|
@ -172,32 +164,43 @@ func (ac *Webhook) Run(stop <-chan struct{}) error {
|
|||
logger.Infof("Delaying admission webhook registration for %v", ac.Options.RegistrationDelay)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-time.After(ac.Options.RegistrationDelay):
|
||||
for _, c := range ac.admissionControllers {
|
||||
if err := c.Register(ctx, ac.Client, caCert); err != nil {
|
||||
logger.Errorw("failed to register webhook", zap.Error(err))
|
||||
return err
|
||||
eg, ctx := errgroup.WithContext(ctx)
|
||||
eg.Go(func() error {
|
||||
select {
|
||||
case <-time.After(ac.Options.RegistrationDelay):
|
||||
// Wait an initial delay before registering
|
||||
case <-stop:
|
||||
return nil
|
||||
}
|
||||
// Register the webhook, and then periodically check that it is up to date.
|
||||
for {
|
||||
for _, c := range ac.admissionControllers {
|
||||
if err := c.Register(ctx, ac.Client, caCert); err != nil {
|
||||
logger.Errorw("failed to register webhook", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
}
|
||||
logger.Info("Successfully registered webhook")
|
||||
select {
|
||||
case <-time.After(10 * time.Minute):
|
||||
case <-stop:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
logger.Info("Successfully registered webhook")
|
||||
case <-stop:
|
||||
return nil
|
||||
}
|
||||
|
||||
serverBootstrapErrCh := make(chan struct{})
|
||||
go func() {
|
||||
})
|
||||
eg.Go(func() error {
|
||||
if err := server.ListenAndServeTLS("", ""); err != nil {
|
||||
logger.Errorw("ListenAndServeTLS for admission webhook returned error", zap.Error(err))
|
||||
close(serverBootstrapErrCh)
|
||||
return err
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
})
|
||||
|
||||
select {
|
||||
case <-stop:
|
||||
return server.Close()
|
||||
case <-serverBootstrapErrCh:
|
||||
return errors.New("webhook server bootstrap failed")
|
||||
case <-ctx.Done():
|
||||
return fmt.Errorf("webhook server bootstrap failed %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue