mirror of https://github.com/knative/caching.git
Auto-update dependencies (#195)
Produced via: `dep ensure -update knative.dev/test-infra knative.dev/pkg` /assign n3wscott /cc n3wscott
This commit is contained in:
parent
f07214572b
commit
5dcbd8b57e
|
@ -966,7 +966,7 @@
|
|||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:107ee62154c011274e913c95b410fffde1c9a7ebb4e972a1428f4927a4f8afe6"
|
||||
digest = "1:26325ee882afecdb033204b8f2d8e69f0d939f5bcc1a1b151233a7d78d74f7dc"
|
||||
name = "knative.dev/pkg"
|
||||
packages = [
|
||||
"apis",
|
||||
|
@ -985,7 +985,7 @@
|
|||
"metrics/metricskey",
|
||||
]
|
||||
pruneopts = "T"
|
||||
revision = "d5698e90e262503c568a6abc645a0f34dcec385f"
|
||||
revision = "7ddd3b6a42f6c3db48561e5d9525c66b546bab01"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
@ -996,7 +996,7 @@
|
|||
"tools/dep-collector",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "25ea2a3bc5b89b01ebd564ee53bb737b2c4105e0"
|
||||
revision = "7086222c769000dd2122c44de8f43bbb335ad81a"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:8730e0150dfb2b7e173890c8b9868e7a273082ef8e39f4940e3506a481cf895c"
|
||||
|
|
|
@ -1412,10 +1412,12 @@
|
|||
"k8s.io/api/core/v1",
|
||||
"k8s.io/api/extensions/v1beta1",
|
||||
"k8s.io/api/rbac/v1",
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1",
|
||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset",
|
||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake",
|
||||
"k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions",
|
||||
"k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1",
|
||||
"k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1",
|
||||
"k8s.io/apimachinery/pkg/api/apitesting/fuzzer",
|
||||
"k8s.io/apimachinery/pkg/api/apitesting/roundtrip",
|
||||
"k8s.io/apimachinery/pkg/api/equality",
|
||||
|
|
|
@ -59,7 +59,7 @@ aliases:
|
|||
- vaikas
|
||||
|
||||
webhook-approvers:
|
||||
- dprotaso
|
||||
- mattmoor
|
||||
- grantr
|
||||
- tcnghia
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ import (
|
|||
type Destination struct {
|
||||
// Ref points to an Addressable.
|
||||
// +optional
|
||||
Ref *KnativeReference `json:"ref,omitempty"`
|
||||
Ref *KReference `json:"ref,omitempty"`
|
||||
|
||||
// URI can be an absolute URL(non-empty scheme and non-empty host) pointing to the target or a relative URI. Relative URIs will be resolved using the base URI retrieved from Ref.
|
||||
// +optional
|
||||
|
@ -61,9 +61,9 @@ func ValidateDestination(ctx context.Context, dest Destination) *apis.FieldError
|
|||
return nil
|
||||
}
|
||||
|
||||
// GetRef gets the KnativeReference from this Destination, if one is present. If no ref is present,
|
||||
// GetRef gets the KReference from this Destination, if one is present. If no ref is present,
|
||||
// then nil is returned.
|
||||
func (dest *Destination) GetRef() *KnativeReference {
|
||||
func (dest *Destination) GetRef() *KReference {
|
||||
if dest == nil {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -22,9 +22,9 @@ import (
|
|||
"knative.dev/pkg/apis"
|
||||
)
|
||||
|
||||
// KnativeReference contains enough information to refer to another object.
|
||||
// KReference contains enough information to refer to another object.
|
||||
// It's a trimmed down version of corev1.ObjectReference.
|
||||
type KnativeReference struct {
|
||||
type KReference struct {
|
||||
// Kind of the referent.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
Kind string `json:"kind"`
|
||||
|
@ -43,13 +43,12 @@ type KnativeReference struct {
|
|||
APIVersion string `json:"apiVersion"`
|
||||
}
|
||||
|
||||
func (kr *KnativeReference) Validate(ctx context.Context) *apis.FieldError {
|
||||
func (kr *KReference) Validate(ctx context.Context) *apis.FieldError {
|
||||
var errs *apis.FieldError
|
||||
if kr == nil {
|
||||
errs = errs.Also(apis.ErrMissingField("name"))
|
||||
errs = errs.Also(apis.ErrMissingField("apiVersion"))
|
||||
errs = errs.Also(apis.ErrMissingField("kind"))
|
||||
return errs
|
||||
return errs.Also(apis.ErrMissingField("name")).
|
||||
Also(apis.ErrMissingField("apiVersion")).
|
||||
Also(apis.ErrMissingField("kind"))
|
||||
}
|
||||
if kr.Name == "" {
|
||||
errs = errs.Also(apis.ErrMissingField("name"))
|
||||
|
@ -63,7 +62,7 @@ func (kr *KnativeReference) Validate(ctx context.Context) *apis.FieldError {
|
|||
return errs
|
||||
}
|
||||
|
||||
func (kr *KnativeReference) SetDefaults(ctx context.Context) {
|
||||
func (kr *KReference) SetDefaults(ctx context.Context) {
|
||||
if kr.Namespace == "" {
|
||||
kr.Namespace = apis.ParentMeta(ctx).Namespace
|
||||
}
|
||||
|
|
|
@ -177,7 +177,7 @@ func (in *Destination) DeepCopyInto(out *Destination) {
|
|||
*out = *in
|
||||
if in.Ref != nil {
|
||||
in, out := &in.Ref, &out.Ref
|
||||
*out = new(KnativeReference)
|
||||
*out = new(KReference)
|
||||
**out = **in
|
||||
}
|
||||
if in.URI != nil {
|
||||
|
@ -198,6 +198,22 @@ func (in *Destination) DeepCopy() *Destination {
|
|||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KReference) DeepCopyInto(out *KReference) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KReference.
|
||||
func (in *KReference) DeepCopy() *KReference {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(KReference)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KResource) DeepCopyInto(out *KResource) {
|
||||
*out = *in
|
||||
|
@ -258,22 +274,6 @@ func (in *KResourceList) DeepCopyObject() runtime.Object {
|
|||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KnativeReference) DeepCopyInto(out *KnativeReference) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KnativeReference.
|
||||
func (in *KnativeReference) DeepCopy() *KnativeReference {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(KnativeReference)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *PodSpecable) DeepCopyInto(out *PodSpecable) {
|
||||
*out = *in
|
||||
|
|
|
@ -244,7 +244,7 @@ func (r *reporter) ReportReconcile(duration time.Duration, key, success string)
|
|||
return err
|
||||
}
|
||||
|
||||
metrics.Record(ctx, reconcileCountStat.M(1))
|
||||
metrics.Record(ctx, reconcileLatencyStat.M(int64(duration/time.Millisecond)))
|
||||
metrics.RecordBatch(ctx, reconcileCountStat.M(1),
|
||||
reconcileLatencyStat.M(duration.Milliseconds()))
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -60,7 +60,15 @@ ${CODEGEN_PKG}/generate-groups.sh "deepcopy" \
|
|||
|
||||
# Depends on generate-groups.sh to install bin/deepcopy-gen
|
||||
${GOPATH}/bin/deepcopy-gen --input-dirs \
|
||||
knative.dev/pkg/apis,knative.dev/pkg/tracker,knative.dev/pkg/logging,knative.dev/pkg/metrics,knative.dev/pkg/testing,knative.dev/pkg/testing/duck \
|
||||
$(echo \
|
||||
knative.dev/pkg/apis \
|
||||
knative.dev/pkg/tracker \
|
||||
knative.dev/pkg/logging \
|
||||
knative.dev/pkg/metrics \
|
||||
knative.dev/pkg/testing \
|
||||
knative.dev/pkg/testing/duck \
|
||||
knative.dev/pkg/webhook/resourcesemantics/conversion/internal \
|
||||
| sed "s/ /,/g") \
|
||||
-O zz_generated.deepcopy \
|
||||
--go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt
|
||||
|
||||
|
|
|
@ -164,14 +164,15 @@ func MainWithConfig(ctx context.Context, component string, cfg *rest.Config, cto
|
|||
|
||||
// Based on the reconcilers we have linked, build up the set of controllers to run.
|
||||
controllers := make([]*controller.Impl, 0, len(ctors))
|
||||
webhooks := make([]webhook.AdmissionController, 0)
|
||||
webhooks := make([]interface{}, 0)
|
||||
for _, cf := range ctors {
|
||||
ctrl := cf(ctx, cmw)
|
||||
controllers = append(controllers, ctrl)
|
||||
|
||||
// Build a list of any reconcilers that implement webhook.AdmissionController
|
||||
if ac, ok := ctrl.Reconciler.(webhook.AdmissionController); ok {
|
||||
webhooks = append(webhooks, ac)
|
||||
switch c := ctrl.Reconciler.(type) {
|
||||
case webhook.AdmissionController, webhook.ConversionController:
|
||||
webhooks = append(webhooks, c)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,7 +223,7 @@ func MainWithConfig(ctx context.Context, component string, cfg *rest.Config, cto
|
|||
|
||||
wh, err := webhook.New(ctx, webhooks)
|
||||
if err != nil {
|
||||
logger.Fatalw("Failed to create admission controller", zap.Error(err))
|
||||
logger.Fatalw("Failed to create webhook", zap.Error(err))
|
||||
}
|
||||
eg.Go(func() error {
|
||||
return wh.Run(ctx.Done())
|
||||
|
|
|
@ -94,7 +94,7 @@ func CheckDistributionData(t test.T, name string, wantTags map[string]string, ex
|
|||
// reported are tagged with the tags in wantTags and that wantValue matches reported last value.
|
||||
func CheckLastValueData(t test.T, name string, wantTags map[string]string, wantValue float64) {
|
||||
t.Helper()
|
||||
if row := checkExactlyOneRow(t, name); row != nil {
|
||||
if row := lastRow(t, name); row != nil {
|
||||
checkRowTags(t, row, name, wantTags)
|
||||
|
||||
if s, ok := row.Data.(*view.LastValueData); !ok {
|
||||
|
@ -135,6 +135,21 @@ func Unregister(names ...string) {
|
|||
}
|
||||
}
|
||||
|
||||
func lastRow(t test.T, name string) *view.Row {
|
||||
t.Helper()
|
||||
d, err := view.RetrieveData(name)
|
||||
if err != nil {
|
||||
t.Error("Reporter.Report() error", "metric", name, "error", err)
|
||||
return nil
|
||||
}
|
||||
if len(d) < 1 {
|
||||
t.Error("Reporter.Report() wrong length", "metric", name, "got", len(d), "want at least", 1)
|
||||
return nil
|
||||
}
|
||||
|
||||
return d[len(d)-1]
|
||||
}
|
||||
|
||||
func checkExactlyOneRow(t test.T, name string) *view.Row {
|
||||
t.Helper()
|
||||
d, err := view.RetrieveData(name)
|
||||
|
|
|
@ -106,7 +106,7 @@ func (r *URIResolver) URIFromDestination(dest duckv1beta1.Destination, parent in
|
|||
// URIFromDestinationV1 resolves a v1.Destination into a URL.
|
||||
func (r *URIResolver) URIFromDestinationV1(dest duckv1.Destination, parent interface{}) (*apis.URL, error) {
|
||||
if dest.Ref != nil {
|
||||
url, err := r.URIFromKnativeReference(dest.Ref, parent)
|
||||
url, err := r.URIFromKReference(dest.Ref, parent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ func (r *URIResolver) URIFromDestinationV1(dest duckv1.Destination, parent inter
|
|||
return nil, errors.New("destination missing Ref and URI, expected at least one")
|
||||
}
|
||||
|
||||
func (r *URIResolver) URIFromKnativeReference(ref *duckv1.KnativeReference, parent interface{}) (*apis.URL, error) {
|
||||
func (r *URIResolver) URIFromKReference(ref *duckv1.KReference, parent interface{}) (*apis.URL, error) {
|
||||
return r.URIFromObjectReference(&corev1.ObjectReference{Name: ref.Name, Namespace: ref.Namespace, APIVersion: ref.APIVersion, Kind: ref.Kind}, parent)
|
||||
}
|
||||
|
||||
|
|
|
@ -58,9 +58,11 @@ type Request struct {
|
|||
// Addons: cluster addons to be added to cluster, such as istio
|
||||
Addons []string
|
||||
|
||||
// EnableWorkloadIdentity: whether to enable Workload Identity -
|
||||
// https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity or not
|
||||
// EnableWorkloadIdentity: whether to enable Workload Identity for this cluster
|
||||
EnableWorkloadIdentity bool
|
||||
|
||||
// ServiceAccount: service account that will be used on this cluster
|
||||
ServiceAccount string
|
||||
}
|
||||
|
||||
// DeepCopy will make a deepcopy of the request struct.
|
||||
|
@ -77,6 +79,7 @@ func (r *Request) DeepCopy() *Request {
|
|||
Zone: r.Zone,
|
||||
Addons: r.Addons,
|
||||
EnableWorkloadIdentity: r.EnableWorkloadIdentity,
|
||||
ServiceAccount: r.ServiceAccount,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,6 +149,12 @@ func NewCreateClusterRequest(request *Request) (*container.CreateClusterRequest,
|
|||
IdentityNamespace: request.Project + ".svc.id.goog",
|
||||
}
|
||||
}
|
||||
if request.ServiceAccount != "" {
|
||||
// The Google Cloud Platform Service Account to be used by the node VMs.
|
||||
// If a service account is specified, the cloud-platform and userinfo.email scopes are used.
|
||||
// If no Service Account is specified, the project default service account is used.
|
||||
ccr.Cluster.NodePools[0].Config.ServiceAccount = request.ServiceAccount
|
||||
}
|
||||
|
||||
// Manage the GKE cluster version. Only one of initial cluster version or release channel can be specified.
|
||||
if request.ReleaseChannel != "" {
|
||||
|
|
|
@ -22,7 +22,9 @@ import (
|
|||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
container "google.golang.org/api/container/v1beta1"
|
||||
|
||||
"knative.dev/pkg/test/gke"
|
||||
"knative.dev/pkg/testutils/clustermanager/e2e-tests/boskos"
|
||||
"knative.dev/pkg/testutils/clustermanager/e2e-tests/common"
|
||||
|
@ -36,7 +38,6 @@ const (
|
|||
DefaultGKEZone = ""
|
||||
regionEnv = "E2E_CLUSTER_REGION"
|
||||
backupRegionEnv = "E2E_CLUSTER_BACKUP_REGIONS"
|
||||
defaultGKEVersion = "latest"
|
||||
DefaultResourceType = boskos.GKEProjectResource
|
||||
|
||||
ClusterRunning = "RUNNING"
|
||||
|
@ -231,7 +232,7 @@ func (gc *GKECluster) Acquire() error {
|
|||
return nil
|
||||
}
|
||||
// Creating cluster
|
||||
log.Printf("Creating cluster %q in region %q zone %q with:\n%+v", clusterName, region, request.Zone, gc.Request)
|
||||
log.Printf("Creating cluster %q in region %q zone %q with:\n%+v", clusterName, region, request.Zone, spew.Sdump(rb))
|
||||
err = gc.operations.CreateCluster(gc.Project, region, request.Zone, rb)
|
||||
if err == nil {
|
||||
cluster, err = gc.operations.GetCluster(gc.Project, region, request.Zone, rb.Cluster.Name)
|
||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
package pkg
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
@ -41,6 +42,12 @@ const (
|
|||
statusStopping = "STOPPING"
|
||||
)
|
||||
|
||||
// Extra configurations we want to support for cluster creation request.
|
||||
var (
|
||||
enableWorkloadIdentity = flag.Bool("enable-workload-identity", false, "whether to enable Workload Identity")
|
||||
serviceAccount = flag.String("service-account", "", "service account that will be used on this cluster")
|
||||
)
|
||||
|
||||
type gkeClient struct {
|
||||
ops gke.SDKOperations
|
||||
}
|
||||
|
@ -237,12 +244,14 @@ func (gc *gkeClient) createClusterWithRetries(gcpProject, name string, config Cl
|
|||
addons = strings.Split(config.Addons, ",")
|
||||
}
|
||||
req := &gke.Request{
|
||||
Project: gcpProject,
|
||||
ClusterName: name,
|
||||
MinNodes: config.NodeCount,
|
||||
MaxNodes: config.NodeCount,
|
||||
NodeType: config.NodeType,
|
||||
Addons: addons,
|
||||
Project: gcpProject,
|
||||
ClusterName: name,
|
||||
MinNodes: config.NodeCount,
|
||||
MaxNodes: config.NodeCount,
|
||||
NodeType: config.NodeType,
|
||||
Addons: addons,
|
||||
EnableWorkloadIdentity: *enableWorkloadIdentity,
|
||||
ServiceAccount: *serviceAccount,
|
||||
}
|
||||
creq, err := gke.NewCreateClusterRequest(req)
|
||||
if err != nil {
|
||||
|
|
|
@ -51,7 +51,7 @@ func main() {
|
|||
case get:
|
||||
_, err = actions.Get(o)
|
||||
default:
|
||||
err = errors.New("Must pass one of --create, --delete, --get")
|
||||
err = errors.New("must pass one of --create, --delete, --get")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
Copyright 2020 The Knative Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"go.uber.org/zap"
|
||||
apixv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
"knative.dev/pkg/logging"
|
||||
)
|
||||
|
||||
// ConversionController provides the interface for different conversion controllers
|
||||
type ConversionController interface {
|
||||
// Path returns the path that this particular conversion controller serves on.
|
||||
Path() string
|
||||
|
||||
// Convert is the callback which is invoked when an HTTPS request comes in on Path().
|
||||
Convert(context.Context, *apixv1beta1.ConversionRequest) *apixv1beta1.ConversionResponse
|
||||
}
|
||||
|
||||
func conversionHandler(rootLogger *zap.SugaredLogger, stats StatsReporter, c ConversionController) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
logger := rootLogger
|
||||
logger.Infof("Webhook ServeHTTP request=%#v", r)
|
||||
|
||||
var review apixv1beta1.ConversionReview
|
||||
if err := json.NewDecoder(r.Body).Decode(&review); err != nil {
|
||||
http.Error(w, fmt.Sprintf("could not decode body: %v", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
logger = logger.With(
|
||||
zap.String("uid", string(review.Request.UID)),
|
||||
zap.String("desiredAPIVersion", review.Request.DesiredAPIVersion),
|
||||
)
|
||||
|
||||
ctx := logging.WithLogger(r.Context(), logger)
|
||||
response := apixv1beta1.ConversionReview{
|
||||
Response: c.Convert(ctx, review.Request),
|
||||
}
|
||||
|
||||
if err := json.NewEncoder(w).Encode(response); err != nil {
|
||||
http.Error(w, fmt.Sprintf("could encode response: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO(dprotaso) - figure out what metrics we want reported
|
||||
// if stats != nil {
|
||||
// // Only report valid requests
|
||||
// stats.ReportRequest(review.Request, response.Response, time.Since(ttStart))
|
||||
// }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
Copyright 2020 The Knative Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package conversion
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"knative.dev/pkg/apis"
|
||||
apixclient "knative.dev/pkg/client/injection/apiextensions/client"
|
||||
crdinformer "knative.dev/pkg/client/injection/apiextensions/informers/apiextensions/v1beta1/customresourcedefinition"
|
||||
secretinformer "knative.dev/pkg/client/injection/kube/informers/core/v1/secret"
|
||||
"knative.dev/pkg/controller"
|
||||
"knative.dev/pkg/logging"
|
||||
"knative.dev/pkg/system"
|
||||
"knative.dev/pkg/webhook"
|
||||
)
|
||||
|
||||
// ConvertibleObject defines the functionality our API types
|
||||
// are required to implement in order to be convertible from
|
||||
// one version to another
|
||||
//
|
||||
// Optionally if the object implements apis.Defaultable the
|
||||
// ConversionController will apply defaults before returning
|
||||
// the response
|
||||
type ConvertibleObject interface {
|
||||
// ConvertUp(ctx)
|
||||
// ConvertDown(ctx)
|
||||
apis.Convertible
|
||||
|
||||
// DeepCopyObject()
|
||||
// GetObjectKind() => SetGroupVersionKind(gvk)
|
||||
runtime.Object
|
||||
}
|
||||
|
||||
// GroupKindConversion specifies how a specific Kind for a given
|
||||
// group should be converted
|
||||
type GroupKindConversion struct {
|
||||
// DefinitionName specifies the CustomResourceDefinition that should
|
||||
// be reconciled with by the controller.
|
||||
//
|
||||
// The conversion webhook configuration will be updated
|
||||
// when the CA bundle changes
|
||||
DefinitionName string
|
||||
|
||||
// HubVersion specifies which version of the CustomResource supports
|
||||
// convertions to and from all types
|
||||
//
|
||||
// It is expected that the Zygotes map contains an entry for the
|
||||
// specified HubVersion
|
||||
HubVersion string
|
||||
|
||||
// Zygotes contains a map of version strings (ie. v1, v2) to empty
|
||||
// ConvertibleObject objects
|
||||
//
|
||||
// During a conversion request these zygotes will be deep copied
|
||||
// and manipulated using the apis.Convertible interface
|
||||
Zygotes map[string]ConvertibleObject
|
||||
}
|
||||
|
||||
// NewConversionController returns a K8s controller that will
|
||||
// will reconcile CustomResourceDefinitions and update their
|
||||
// conversion webhook attributes such as path & CA bundle.
|
||||
//
|
||||
// Additionally the controller's Reconciler implements
|
||||
// webhook.ConversionController for the purposes of converting
|
||||
// resources between different versions
|
||||
func NewConversionController(
|
||||
ctx context.Context,
|
||||
path string,
|
||||
kinds map[schema.GroupKind]GroupKindConversion,
|
||||
withContext func(context.Context) context.Context,
|
||||
) *controller.Impl {
|
||||
|
||||
logger := logging.FromContext(ctx)
|
||||
secretInformer := secretinformer.Get(ctx)
|
||||
crdInformer := crdinformer.Get(ctx)
|
||||
client := apixclient.Get(ctx)
|
||||
options := webhook.GetOptions(ctx)
|
||||
|
||||
r := &reconciler{
|
||||
kinds: kinds,
|
||||
path: path,
|
||||
secretName: options.SecretName,
|
||||
withContext: withContext,
|
||||
|
||||
client: client,
|
||||
secretLister: secretInformer.Lister(),
|
||||
crdLister: crdInformer.Lister(),
|
||||
}
|
||||
|
||||
c := controller.NewImpl(r, logger, "ConversionWebhook")
|
||||
|
||||
// Reconciler when the named CRDs change.
|
||||
for _, gkc := range kinds {
|
||||
name := gkc.DefinitionName
|
||||
|
||||
crdInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{
|
||||
FilterFunc: controller.FilterWithName(name),
|
||||
Handler: controller.HandleAll(c.Enqueue),
|
||||
})
|
||||
|
||||
sentinel := c.EnqueueSentinel(types.NamespacedName{Name: name})
|
||||
|
||||
// Reconcile when the cert bundle changes.
|
||||
secretInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{
|
||||
FilterFunc: controller.FilterWithNameAndNamespace(system.Namespace(), options.SecretName),
|
||||
Handler: controller.HandleAll(sentinel),
|
||||
})
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
Copyright 2020 The Knative Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package conversion
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"go.uber.org/zap"
|
||||
apixv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"knative.dev/pkg/apis"
|
||||
"knative.dev/pkg/logging"
|
||||
)
|
||||
|
||||
// Convert implements webhook.ConversionController
|
||||
func (r *reconciler) Convert(
|
||||
ctx context.Context,
|
||||
req *apixv1beta1.ConversionRequest,
|
||||
) *apixv1beta1.ConversionResponse {
|
||||
|
||||
if r.withContext != nil {
|
||||
ctx = r.withContext(ctx)
|
||||
}
|
||||
|
||||
res := &apixv1beta1.ConversionResponse{
|
||||
UID: req.UID,
|
||||
Result: metav1.Status{
|
||||
Status: metav1.StatusSuccess,
|
||||
},
|
||||
}
|
||||
|
||||
result := make([]runtime.RawExtension, 0, len(req.Objects))
|
||||
|
||||
for _, obj := range req.Objects {
|
||||
converted, err := r.convert(ctx, obj, req.DesiredAPIVersion)
|
||||
if err != nil {
|
||||
res.Result.Status = metav1.StatusFailure
|
||||
res.Result.Message = err.Error()
|
||||
break
|
||||
}
|
||||
|
||||
result = append(result, converted)
|
||||
}
|
||||
|
||||
res.ConvertedObjects = result
|
||||
return res
|
||||
}
|
||||
|
||||
func (r *reconciler) convert(
|
||||
ctx context.Context,
|
||||
inRaw runtime.RawExtension,
|
||||
targetVersion string,
|
||||
) (outRaw runtime.RawExtension, err error) {
|
||||
|
||||
logger := logging.FromContext(ctx)
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
logger.Errorf("Conversion failed: %s", err)
|
||||
}
|
||||
}()
|
||||
|
||||
inGVK, err := parseGVK(inRaw)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
logger.Infof("Converting %s to version %s", formatGVK(inGVK), targetVersion)
|
||||
|
||||
inGK := inGVK.GroupKind()
|
||||
conv, ok := r.kinds[inGK]
|
||||
if !ok {
|
||||
err = fmt.Errorf("no conversion support for type %s", formatGK(inGVK.GroupKind()))
|
||||
return
|
||||
}
|
||||
|
||||
outGVK, err := parseAPIVersion(targetVersion, inGK.Kind)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
inZygote, ok := conv.Zygotes[inGVK.Version]
|
||||
if !ok {
|
||||
err = fmt.Errorf("conversion not supported for type %s", formatGVK(inGVK))
|
||||
return
|
||||
}
|
||||
outZygote, ok := conv.Zygotes[outGVK.Version]
|
||||
if !ok {
|
||||
err = fmt.Errorf("conversion not supported for type %s", formatGVK(outGVK))
|
||||
return
|
||||
}
|
||||
hubZygote, ok := conv.Zygotes[conv.HubVersion]
|
||||
if !ok {
|
||||
inGK := inGVK.GroupKind()
|
||||
err = fmt.Errorf("conversion not supported for type %s", formatGK(inGK))
|
||||
return
|
||||
}
|
||||
|
||||
in := inZygote.DeepCopyObject().(ConvertibleObject)
|
||||
hub := hubZygote.DeepCopyObject().(ConvertibleObject)
|
||||
out := outZygote.DeepCopyObject().(ConvertibleObject)
|
||||
|
||||
hubGVK := inGVK.GroupKind().WithVersion(conv.HubVersion)
|
||||
logger = logger.With(
|
||||
zap.String("inputType", formatGVK(inGVK)),
|
||||
zap.String("outputType", formatGVK(outGVK)),
|
||||
zap.String("hubType", formatGVK(hubGVK)),
|
||||
)
|
||||
|
||||
// TODO(dprotaso) - potentially error on unknown fields
|
||||
if err = json.Unmarshal(inRaw.Raw, &in); err != nil {
|
||||
err = fmt.Errorf("unable to unmarshal input: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
if inGVK.Version == conv.HubVersion {
|
||||
hub = in
|
||||
} else if err = hub.ConvertDown(ctx, in); err != nil {
|
||||
err = fmt.Errorf("conversion failed to version %s for type %s - %s", outGVK.Version, formatGVK(inGVK), err)
|
||||
return
|
||||
}
|
||||
|
||||
if outGVK.Version == conv.HubVersion {
|
||||
out = hub
|
||||
} else if err = hub.ConvertUp(ctx, out); err != nil {
|
||||
err = fmt.Errorf("conversion failed to version %s for type %s - %s", outGVK.Version, formatGVK(inGVK), err)
|
||||
return
|
||||
}
|
||||
|
||||
out.GetObjectKind().SetGroupVersionKind(outGVK)
|
||||
|
||||
if defaultable, ok := out.(apis.Defaultable); ok {
|
||||
defaultable.SetDefaults(ctx)
|
||||
}
|
||||
|
||||
if outRaw.Raw, err = json.Marshal(out); err != nil {
|
||||
err = fmt.Errorf("unable to marshal output: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func parseGVK(in runtime.RawExtension) (gvk schema.GroupVersionKind, err error) {
|
||||
var typeMeta metav1.TypeMeta
|
||||
|
||||
if err = json.Unmarshal(in.Raw, &typeMeta); err != nil {
|
||||
err = fmt.Errorf("error parsing type meta %q - %s", string(in.Raw), err)
|
||||
return
|
||||
}
|
||||
|
||||
gv, err := schema.ParseGroupVersion(typeMeta.APIVersion)
|
||||
gvk = gv.WithKind(typeMeta.Kind)
|
||||
|
||||
if gvk.Group == "" || gvk.Version == "" || gvk.Kind == "" {
|
||||
err = fmt.Errorf("invalid GroupVersionKind %v", gvk)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func parseAPIVersion(apiVersion string, kind string) (schema.GroupVersionKind, error) {
|
||||
gv, err := schema.ParseGroupVersion(apiVersion)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("desired API version %q is not valid", apiVersion)
|
||||
return schema.GroupVersionKind{}, err
|
||||
}
|
||||
|
||||
if !isValidGV(gv) {
|
||||
err = fmt.Errorf("desired API version %q is not valid", apiVersion)
|
||||
return schema.GroupVersionKind{}, err
|
||||
}
|
||||
|
||||
return gv.WithKind(kind), nil
|
||||
}
|
||||
|
||||
func formatGVK(gvk schema.GroupVersionKind) string {
|
||||
return fmt.Sprintf("[kind=%s group=%s version=%s]", gvk.Kind, gvk.Group, gvk.Version)
|
||||
}
|
||||
|
||||
func formatGK(gk schema.GroupKind) string {
|
||||
return fmt.Sprintf("[kind=%s group=%s]", gk.Kind, gk.Group)
|
||||
}
|
||||
|
||||
func isValidGV(gk schema.GroupVersion) bool {
|
||||
return gk.Group != "" && gk.Version != ""
|
||||
}
|
278
vendor/knative.dev/pkg/webhook/resourcesemantics/conversion/internal/types.go
vendored
Normal file
278
vendor/knative.dev/pkg/webhook/resourcesemantics/conversion/internal/types.go
vendored
Normal file
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
Copyright 2020 The Knative Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"knative.dev/pkg/apis"
|
||||
)
|
||||
|
||||
const (
|
||||
// Group specifies the group of the test resource
|
||||
Group = "webhook.pkg.knative.dev"
|
||||
|
||||
// Kind specifies the kind of the test resource
|
||||
Kind = "Resource"
|
||||
|
||||
// ErrorMarshal when assigned to the Spec.Property of the ErrorResource
|
||||
// will cause json marshalling of the resource to fail
|
||||
ErrorMarshal = "marshal"
|
||||
|
||||
// ErrorUnmarshal when assigned to the Spec.Property of the ErrorResource
|
||||
// will cause json unmarshalling of the resource to fail
|
||||
ErrorUnmarshal = "unmarshal"
|
||||
|
||||
// ErrorConvertUp when assigned to the Spec.Property of the ErrorResource
|
||||
// will cause ConvertUp to fail
|
||||
ErrorConvertUp = "convertUp"
|
||||
|
||||
// ErrorConvertDown when assigned to the Spec.Property of the ErrorResource
|
||||
// will cause ConvertDown to fail
|
||||
ErrorConvertDown = "convertDown"
|
||||
)
|
||||
|
||||
type (
|
||||
// V1Resource will never has a prefix or suffix on Spec.Property
|
||||
// This type is used for testing conversion webhooks
|
||||
//
|
||||
// +k8s:deepcopy-gen=true
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
V1Resource struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
Spec Spec `json:"spec"`
|
||||
}
|
||||
|
||||
// V2Resource will always have a 'prefix/' in front of it's property
|
||||
// This type is used for testing conversion webhooks
|
||||
//
|
||||
// +k8s:deepcopy-gen=true
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
V2Resource struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
Spec Spec `json:"spec"`
|
||||
}
|
||||
|
||||
// V3Resource will always have a '/suffix' in front of it's property
|
||||
// This type is used for testing conversion webhooks
|
||||
//
|
||||
// +k8s:deepcopy-gen=true
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
V3Resource struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
Spec SpecWithDefault `json:"spec"`
|
||||
}
|
||||
|
||||
// ErrorResource explodes in various settings depending on the property
|
||||
// set. Use the Error* constants
|
||||
//
|
||||
//This type is used for testing conversion webhooks
|
||||
//
|
||||
// +k8s:deepcopy-gen=true
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
ErrorResource struct {
|
||||
// We embed the V1Resource as an easy way to still marshal & unmarshal
|
||||
// this type without infinite loops - since we override the methods
|
||||
// in order to induce failures
|
||||
V1Resource `json:",inline"`
|
||||
}
|
||||
|
||||
// Spec holds our fancy string property
|
||||
Spec struct {
|
||||
Property string `json:"prop"`
|
||||
}
|
||||
|
||||
// SpecWithDefault holds two fancy string properties
|
||||
SpecWithDefault struct {
|
||||
Property string `json:"prop"`
|
||||
NewProperty string `json:"defaulted_prop"`
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
_ apis.Convertible = (*V1Resource)(nil)
|
||||
_ apis.Convertible = (*V2Resource)(nil)
|
||||
_ apis.Convertible = (*V3Resource)(nil)
|
||||
_ apis.Convertible = (*ErrorResource)(nil)
|
||||
|
||||
_ apis.Defaultable = (*V3Resource)(nil)
|
||||
)
|
||||
|
||||
// NewV1 returns a V1Resource with Spec.Property set
|
||||
// to prop
|
||||
func NewV1(prop string) *V1Resource {
|
||||
return &V1Resource{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: Kind,
|
||||
APIVersion: Group + "/v1",
|
||||
},
|
||||
Spec: Spec{
|
||||
Property: prop,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// NewV2 returns a V2Resource with Spec.Property set
|
||||
// to 'prefix/' + prop
|
||||
func NewV2(prop string) *V2Resource {
|
||||
return &V2Resource{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: Kind,
|
||||
APIVersion: Group + "/v2",
|
||||
},
|
||||
Spec: Spec{
|
||||
Property: fmt.Sprintf("prefix/%s", prop),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// NewV3 returns a V3Resource with Spec.Property set
|
||||
// to prop + '/suffix'
|
||||
func NewV3(prop string) *V3Resource {
|
||||
v3 := &V3Resource{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: Kind,
|
||||
APIVersion: Group + "/v3",
|
||||
},
|
||||
Spec: SpecWithDefault{
|
||||
Property: fmt.Sprintf("%s/suffix", prop),
|
||||
},
|
||||
}
|
||||
v3.SetDefaults(context.Background())
|
||||
return v3
|
||||
}
|
||||
|
||||
// NewErrorResource returns an ErrorResource with Spec.Property set
|
||||
// to failure
|
||||
func NewErrorResource(failure string) *ErrorResource {
|
||||
return &ErrorResource{
|
||||
V1Resource: V1Resource{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: Kind,
|
||||
APIVersion: Group + "/error",
|
||||
},
|
||||
Spec: Spec{
|
||||
Property: failure,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertUp implements apis.Convertible
|
||||
func (r *V1Resource) ConvertUp(ctx context.Context, to apis.Convertible) error {
|
||||
switch sink := to.(type) {
|
||||
case *V2Resource:
|
||||
sink.Spec.Property = "prefix/" + r.Spec.Property
|
||||
case *V3Resource:
|
||||
sink.Spec.Property = r.Spec.Property + "/suffix"
|
||||
case *ErrorResource:
|
||||
sink.Spec.Property = r.Spec.Property
|
||||
case *V1Resource:
|
||||
sink.Spec.Property = r.Spec.Property
|
||||
default:
|
||||
return fmt.Errorf("unsupported type %T", sink)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ConvertDown implements apis.Convertible
|
||||
func (r *V1Resource) ConvertDown(ctx context.Context, from apis.Convertible) error {
|
||||
switch source := from.(type) {
|
||||
case *V2Resource:
|
||||
r.Spec.Property = strings.TrimPrefix(source.Spec.Property, "prefix/")
|
||||
case *V3Resource:
|
||||
r.Spec.Property = strings.TrimSuffix(source.Spec.Property, "/suffix")
|
||||
case *ErrorResource:
|
||||
r.Spec.Property = source.Spec.Property
|
||||
case *V1Resource:
|
||||
r.Spec.Property = source.Spec.Property
|
||||
default:
|
||||
return fmt.Errorf("unsupported type %T", source)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetDefaults implements apis.Defaultable
|
||||
func (r *V3Resource) SetDefaults(ctx context.Context) {
|
||||
if r.Spec.NewProperty == "" {
|
||||
r.Spec.NewProperty = "defaulted"
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertUp implements apis.Convertible
|
||||
func (*V2Resource) ConvertUp(ctx context.Context, to apis.Convertible) error {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
// ConvertDown implements apis.Convertible
|
||||
func (*V2Resource) ConvertDown(ctx context.Context, from apis.Convertible) error {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
// ConvertUp implements apis.Convertible
|
||||
func (*V3Resource) ConvertUp(ctx context.Context, to apis.Convertible) error {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
// ConvertDown implements apis.Convertible
|
||||
func (*V3Resource) ConvertDown(ctx context.Context, from apis.Convertible) error {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
// ConvertUp implements apis.Convertible
|
||||
func (e *ErrorResource) ConvertUp(ctx context.Context, to apis.Convertible) error {
|
||||
if e.Spec.Property == ErrorConvertUp {
|
||||
return errors.New("boooom - convert up")
|
||||
}
|
||||
|
||||
return e.V1Resource.ConvertUp(ctx, to)
|
||||
}
|
||||
|
||||
// ConvertDown implements apis.Convertible
|
||||
func (e *ErrorResource) ConvertDown(ctx context.Context, from apis.Convertible) error {
|
||||
err := e.V1Resource.ConvertDown(ctx, from)
|
||||
|
||||
if err == nil && e.Spec.Property == ErrorConvertDown {
|
||||
err = errors.New("boooom - convert down")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler
|
||||
func (e *ErrorResource) UnmarshalJSON(data []byte) (err error) {
|
||||
err = json.Unmarshal(data, &e.V1Resource)
|
||||
if err == nil && e.Spec.Property == ErrorUnmarshal {
|
||||
err = errors.New("boooom - unmarshal json")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalJSON implements json.Marshaler
|
||||
func (e *ErrorResource) MarshalJSON() ([]byte, error) {
|
||||
if e.Spec.Property == ErrorMarshal {
|
||||
return nil, errors.New("boooom - marshal json")
|
||||
}
|
||||
return json.Marshal(e.V1Resource)
|
||||
}
|
131
vendor/knative.dev/pkg/webhook/resourcesemantics/conversion/internal/zz_generated.deepcopy.go
generated
vendored
Normal file
131
vendor/knative.dev/pkg/webhook/resourcesemantics/conversion/internal/zz_generated.deepcopy.go
generated
vendored
Normal file
|
@ -0,0 +1,131 @@
|
|||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 2020 The Knative Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ErrorResource) DeepCopyInto(out *ErrorResource) {
|
||||
*out = *in
|
||||
in.V1Resource.DeepCopyInto(&out.V1Resource)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ErrorResource.
|
||||
func (in *ErrorResource) DeepCopy() *ErrorResource {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ErrorResource)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *ErrorResource) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *V1Resource) DeepCopyInto(out *V1Resource) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
out.Spec = in.Spec
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new V1Resource.
|
||||
func (in *V1Resource) DeepCopy() *V1Resource {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(V1Resource)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *V1Resource) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *V2Resource) DeepCopyInto(out *V2Resource) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
out.Spec = in.Spec
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new V2Resource.
|
||||
func (in *V2Resource) DeepCopy() *V2Resource {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(V2Resource)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *V2Resource) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *V3Resource) DeepCopyInto(out *V3Resource) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
out.Spec = in.Spec
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new V3Resource.
|
||||
func (in *V3Resource) DeepCopy() *V3Resource {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(V3Resource)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *V3Resource) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
Copyright 2020 The Knative Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package conversion
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
apixv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
apixclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
apixlisters "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
corelisters "k8s.io/client-go/listers/core/v1"
|
||||
"knative.dev/pkg/controller"
|
||||
"knative.dev/pkg/kmp"
|
||||
"knative.dev/pkg/logging"
|
||||
"knative.dev/pkg/ptr"
|
||||
"knative.dev/pkg/system"
|
||||
"knative.dev/pkg/webhook"
|
||||
certresources "knative.dev/pkg/webhook/certificates/resources"
|
||||
)
|
||||
|
||||
type reconciler struct {
|
||||
kinds map[schema.GroupKind]GroupKindConversion
|
||||
path string
|
||||
secretName string
|
||||
withContext func(context.Context) context.Context
|
||||
|
||||
secretLister corelisters.SecretLister
|
||||
crdLister apixlisters.CustomResourceDefinitionLister
|
||||
client apixclient.Interface
|
||||
}
|
||||
|
||||
var _ webhook.ConversionController = (*reconciler)(nil)
|
||||
var _ controller.Reconciler = (*reconciler)(nil)
|
||||
|
||||
// Path implements webhook.ConversionController
|
||||
func (r *reconciler) Path() string {
|
||||
return r.path
|
||||
}
|
||||
|
||||
// Reconciler implements controller.Reconciler
|
||||
func (r *reconciler) Reconcile(ctx context.Context, key string) error {
|
||||
logger := logging.FromContext(ctx)
|
||||
|
||||
// Look up the webhook secret, and fetch the CA cert bundle.
|
||||
secret, err := r.secretLister.Secrets(system.Namespace()).Get(r.secretName)
|
||||
if err != nil {
|
||||
logger.Errorf("Error fetching secret: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
cacert, ok := secret.Data[certresources.CACert]
|
||||
if !ok {
|
||||
return fmt.Errorf("secret %q is missing %q key", r.secretName, certresources.CACert)
|
||||
}
|
||||
|
||||
return r.reconcileCRD(ctx, cacert, key)
|
||||
}
|
||||
|
||||
func (r *reconciler) reconcileCRD(ctx context.Context, cacert []byte, key string) error {
|
||||
logger := logging.FromContext(ctx)
|
||||
|
||||
configuredCRD, err := r.crdLister.Get(key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error retrieving crd: %v", err)
|
||||
}
|
||||
|
||||
crd := configuredCRD.DeepCopy()
|
||||
|
||||
if crd.Spec.Conversion == nil ||
|
||||
crd.Spec.Conversion.Strategy != apixv1beta1.WebhookConverter ||
|
||||
crd.Spec.Conversion.WebhookClientConfig == nil ||
|
||||
crd.Spec.Conversion.WebhookClientConfig.Service == nil {
|
||||
return fmt.Errorf("custom resource %q isn't configured for webhook conversion", key)
|
||||
}
|
||||
|
||||
crd.Spec.Conversion.WebhookClientConfig.CABundle = cacert
|
||||
crd.Spec.Conversion.WebhookClientConfig.Service.Path = ptr.String(r.path)
|
||||
|
||||
if ok, err := kmp.SafeEqual(configuredCRD, crd); err != nil {
|
||||
return fmt.Errorf("error diffing custom resource definitions: %v", err)
|
||||
} else if !ok {
|
||||
logger.Infof("updating CRD")
|
||||
crdClient := r.client.ApiextensionsV1beta1().CustomResourceDefinitions()
|
||||
if _, err := crdClient.Update(crd); err != nil {
|
||||
return fmt.Errorf("failed to update webhook: %v", err)
|
||||
}
|
||||
} else {
|
||||
logger.Info("CRD is up to date")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -101,9 +101,9 @@ func (r *reporter) ReportRequest(req *admissionv1beta1.AdmissionRequest, resp *a
|
|||
return err
|
||||
}
|
||||
|
||||
metrics.Record(ctx, requestCountM.M(1))
|
||||
// Convert time.Duration in nanoseconds to milliseconds
|
||||
metrics.Record(ctx, responseTimeInMsecM.M(float64(d/time.Millisecond)))
|
||||
metrics.RecordBatch(ctx, requestCountM.M(1),
|
||||
// Convert time.Duration in nanoseconds to milliseconds
|
||||
responseTimeInMsecM.M(float64(d.Milliseconds())))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
fakeapixclient "knative.dev/pkg/client/injection/apiextensions/client/fake"
|
||||
fakekubeclient "knative.dev/pkg/client/injection/kube/client/fake"
|
||||
fakedynamicclient "knative.dev/pkg/injection/clients/dynamicclient/fake"
|
||||
|
||||
|
@ -61,6 +62,7 @@ func MakeFactory(ctor Ctor) rtesting.Factory {
|
|||
ctx = logging.WithLogger(ctx, logger)
|
||||
|
||||
ctx, kubeClient := fakekubeclient.With(ctx, ls.GetKubeObjects()...)
|
||||
ctx, apixClient := fakeapixclient.With(ctx, ls.GetApiExtensionsObjects()...)
|
||||
ctx, dynamicClient := fakedynamicclient.With(ctx,
|
||||
ls.NewScheme(), ToUnstructured(t, ls.NewScheme(), r.Objects)...)
|
||||
|
||||
|
@ -85,6 +87,13 @@ func MakeFactory(ctor Ctor) rtesting.Factory {
|
|||
return false, nil, nil
|
||||
},
|
||||
)
|
||||
apixClient.PrependReactor("create", "*",
|
||||
func(action ktesting.Action) (bool, runtime.Object, error) {
|
||||
ca := action.(ktesting.CreateAction)
|
||||
ls.IndexerFor(ca.GetObject()).Add(ca.GetObject())
|
||||
return false, nil, nil
|
||||
},
|
||||
)
|
||||
|
||||
// Set up our Controller from the fakes.
|
||||
c := ctor(ctx, &ls, configmap.NewStaticWatcher())
|
||||
|
@ -93,10 +102,11 @@ func MakeFactory(ctor Ctor) rtesting.Factory {
|
|||
|
||||
for _, reactor := range r.WithReactors {
|
||||
kubeClient.PrependReactor("*", "*", reactor)
|
||||
apixClient.PrependReactor("*", "*", reactor)
|
||||
dynamicClient.PrependReactor("*", "*", reactor)
|
||||
}
|
||||
|
||||
actionRecorderList := rtesting.ActionRecorderList{dynamicClient, kubeClient}
|
||||
actionRecorderList := rtesting.ActionRecorderList{dynamicClient, kubeClient, apixClient}
|
||||
eventList := rtesting.EventList{Recorder: eventRecorder}
|
||||
|
||||
return c, actionRecorderList, eventList, statsReporter
|
||||
|
|
|
@ -21,9 +21,13 @@ import (
|
|||
appsv1 "k8s.io/api/apps/v1"
|
||||
autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apixv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
apixlisters "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
fakekubeclientset "k8s.io/client-go/kubernetes/fake"
|
||||
admissionlisters "k8s.io/client-go/listers/admissionregistration/v1beta1"
|
||||
|
||||
fakeapix "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake"
|
||||
appsv1listers "k8s.io/client-go/listers/apps/v1"
|
||||
autoscalingv2beta1listers "k8s.io/client-go/listers/autoscaling/v2beta1"
|
||||
corev1listers "k8s.io/client-go/listers/core/v1"
|
||||
|
@ -38,6 +42,7 @@ var clientSetSchemes = []func(*runtime.Scheme) error{
|
|||
autoscalingv2beta1.AddToScheme,
|
||||
pkgtesting.AddToScheme,
|
||||
pkgducktesting.AddToScheme,
|
||||
fakeapix.AddToScheme,
|
||||
}
|
||||
|
||||
// Listers is used to synthesize informer-style Listers from fixed lists of resources in tests.
|
||||
|
@ -93,6 +98,11 @@ func (l *Listers) GetDuckObjects() []runtime.Object {
|
|||
return l.sorter.ObjectsForSchemeFunc(pkgducktesting.AddToScheme)
|
||||
}
|
||||
|
||||
// GetApiExtensionsObjects filters the Listers initial list of objects to types definite in k8s.io/apiextensions
|
||||
func (l *Listers) GetApiExtensionsObjects() []runtime.Object {
|
||||
return l.sorter.ObjectsForSchemeFunc(fakeapix.AddToScheme)
|
||||
}
|
||||
|
||||
// GetHorizontalPodAutoscalerLister gets lister for HorizontalPodAutoscaler resources.
|
||||
func (l *Listers) GetHorizontalPodAutoscalerLister() autoscalingv2beta1listers.HorizontalPodAutoscalerLister {
|
||||
return autoscalingv2beta1listers.NewHorizontalPodAutoscalerLister(l.IndexerFor(&autoscalingv2beta1.HorizontalPodAutoscaler{}))
|
||||
|
@ -137,3 +147,7 @@ func (l *Listers) GetMutatingWebhookConfigurationLister() admissionlisters.Mutat
|
|||
func (l *Listers) GetValidatingWebhookConfigurationLister() admissionlisters.ValidatingWebhookConfigurationLister {
|
||||
return admissionlisters.NewValidatingWebhookConfigurationLister(l.IndexerFor(&admissionregistrationv1beta1.ValidatingWebhookConfiguration{}))
|
||||
}
|
||||
|
||||
func (l *Listers) GetCustomResourceDefinitionLister() apixlisters.CustomResourceDefinitionLister {
|
||||
return apixlisters.NewCustomResourceDefinitionLister(l.IndexerFor(&apixv1beta1.CustomResourceDefinition{}))
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ type Webhook struct {
|
|||
// New constructs a Webhook
|
||||
func New(
|
||||
ctx context.Context,
|
||||
controllers []AdmissionController,
|
||||
controllers []interface{},
|
||||
) (webhook *Webhook, err error) {
|
||||
|
||||
// ServeMux.Handle panics on duplicate paths
|
||||
|
@ -113,15 +113,27 @@ func New(
|
|||
}
|
||||
|
||||
webhook.mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, fmt.Sprintf("no admission controller registered for: %s", r.URL.Path), http.StatusBadRequest)
|
||||
http.Error(w, fmt.Sprintf("no controller registered for: %s", r.URL.Path), http.StatusBadRequest)
|
||||
})
|
||||
|
||||
for _, c := range controllers {
|
||||
webhook.mux.Handle(
|
||||
c.Path(),
|
||||
admissionHandler(logger, opts.StatsReporter, c),
|
||||
)
|
||||
for _, controller := range controllers {
|
||||
var handler http.Handler
|
||||
var path string
|
||||
|
||||
switch c := controller.(type) {
|
||||
case AdmissionController:
|
||||
handler = admissionHandler(logger, opts.StatsReporter, c)
|
||||
path = c.Path()
|
||||
case ConversionController:
|
||||
handler = conversionHandler(logger, opts.StatsReporter, c)
|
||||
path = c.Path()
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown webhook controller type: %T", controller)
|
||||
}
|
||||
|
||||
webhook.mux.Handle(path, handler)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue