Auto-update dependencies (#121)

Produced via:
  `dep ensure -update knative.dev/test-infra knative.dev/pkg`
/assign mattmoor
This commit is contained in:
mattmoor-sockpuppet 2019-10-25 13:10:35 -07:00 committed by Knative Prow Robot
parent 9075f22c2a
commit ab9eaf9151
5 changed files with 185 additions and 140 deletions

6
Gopkg.lock generated
View File

@ -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"

View File

@ -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
```

View File

@ -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

View File

@ -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
}

View File

@ -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)
}
}