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]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:107ee62154c011274e913c95b410fffde1c9a7ebb4e972a1428f4927a4f8afe6"
|
digest = "1:26325ee882afecdb033204b8f2d8e69f0d939f5bcc1a1b151233a7d78d74f7dc"
|
||||||
name = "knative.dev/pkg"
|
name = "knative.dev/pkg"
|
||||||
packages = [
|
packages = [
|
||||||
"apis",
|
"apis",
|
||||||
|
@ -985,7 +985,7 @@
|
||||||
"metrics/metricskey",
|
"metrics/metricskey",
|
||||||
]
|
]
|
||||||
pruneopts = "T"
|
pruneopts = "T"
|
||||||
revision = "d5698e90e262503c568a6abc645a0f34dcec385f"
|
revision = "7ddd3b6a42f6c3db48561e5d9525c66b546bab01"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
@ -996,7 +996,7 @@
|
||||||
"tools/dep-collector",
|
"tools/dep-collector",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "25ea2a3bc5b89b01ebd564ee53bb737b2c4105e0"
|
revision = "7086222c769000dd2122c44de8f43bbb335ad81a"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:8730e0150dfb2b7e173890c8b9868e7a273082ef8e39f4940e3506a481cf895c"
|
digest = "1:8730e0150dfb2b7e173890c8b9868e7a273082ef8e39f4940e3506a481cf895c"
|
||||||
|
|
|
@ -1412,10 +1412,12 @@
|
||||||
"k8s.io/api/core/v1",
|
"k8s.io/api/core/v1",
|
||||||
"k8s.io/api/extensions/v1beta1",
|
"k8s.io/api/extensions/v1beta1",
|
||||||
"k8s.io/api/rbac/v1",
|
"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",
|
||||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake",
|
"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",
|
||||||
"k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1",
|
"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/fuzzer",
|
||||||
"k8s.io/apimachinery/pkg/api/apitesting/roundtrip",
|
"k8s.io/apimachinery/pkg/api/apitesting/roundtrip",
|
||||||
"k8s.io/apimachinery/pkg/api/equality",
|
"k8s.io/apimachinery/pkg/api/equality",
|
||||||
|
|
|
@ -59,7 +59,7 @@ aliases:
|
||||||
- vaikas
|
- vaikas
|
||||||
|
|
||||||
webhook-approvers:
|
webhook-approvers:
|
||||||
|
- dprotaso
|
||||||
- mattmoor
|
- mattmoor
|
||||||
- grantr
|
|
||||||
- tcnghia
|
- tcnghia
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ import (
|
||||||
type Destination struct {
|
type Destination struct {
|
||||||
// Ref points to an Addressable.
|
// Ref points to an Addressable.
|
||||||
// +optional
|
// +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.
|
// 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
|
// +optional
|
||||||
|
@ -61,9 +61,9 @@ func ValidateDestination(ctx context.Context, dest Destination) *apis.FieldError
|
||||||
return nil
|
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.
|
// then nil is returned.
|
||||||
func (dest *Destination) GetRef() *KnativeReference {
|
func (dest *Destination) GetRef() *KReference {
|
||||||
if dest == nil {
|
if dest == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,9 @@ import (
|
||||||
"knative.dev/pkg/apis"
|
"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.
|
// It's a trimmed down version of corev1.ObjectReference.
|
||||||
type KnativeReference struct {
|
type KReference struct {
|
||||||
// Kind of the referent.
|
// Kind of the referent.
|
||||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||||
Kind string `json:"kind"`
|
Kind string `json:"kind"`
|
||||||
|
@ -43,13 +43,12 @@ type KnativeReference struct {
|
||||||
APIVersion string `json:"apiVersion"`
|
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
|
var errs *apis.FieldError
|
||||||
if kr == nil {
|
if kr == nil {
|
||||||
errs = errs.Also(apis.ErrMissingField("name"))
|
return errs.Also(apis.ErrMissingField("name")).
|
||||||
errs = errs.Also(apis.ErrMissingField("apiVersion"))
|
Also(apis.ErrMissingField("apiVersion")).
|
||||||
errs = errs.Also(apis.ErrMissingField("kind"))
|
Also(apis.ErrMissingField("kind"))
|
||||||
return errs
|
|
||||||
}
|
}
|
||||||
if kr.Name == "" {
|
if kr.Name == "" {
|
||||||
errs = errs.Also(apis.ErrMissingField("name"))
|
errs = errs.Also(apis.ErrMissingField("name"))
|
||||||
|
@ -63,7 +62,7 @@ func (kr *KnativeReference) Validate(ctx context.Context) *apis.FieldError {
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kr *KnativeReference) SetDefaults(ctx context.Context) {
|
func (kr *KReference) SetDefaults(ctx context.Context) {
|
||||||
if kr.Namespace == "" {
|
if kr.Namespace == "" {
|
||||||
kr.Namespace = apis.ParentMeta(ctx).Namespace
|
kr.Namespace = apis.ParentMeta(ctx).Namespace
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,7 +177,7 @@ func (in *Destination) DeepCopyInto(out *Destination) {
|
||||||
*out = *in
|
*out = *in
|
||||||
if in.Ref != nil {
|
if in.Ref != nil {
|
||||||
in, out := &in.Ref, &out.Ref
|
in, out := &in.Ref, &out.Ref
|
||||||
*out = new(KnativeReference)
|
*out = new(KReference)
|
||||||
**out = **in
|
**out = **in
|
||||||
}
|
}
|
||||||
if in.URI != nil {
|
if in.URI != nil {
|
||||||
|
@ -198,6 +198,22 @@ func (in *Destination) DeepCopy() *Destination {
|
||||||
return out
|
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.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *KResource) DeepCopyInto(out *KResource) {
|
func (in *KResource) DeepCopyInto(out *KResource) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
@ -258,22 +274,6 @@ func (in *KResourceList) DeepCopyObject() runtime.Object {
|
||||||
return nil
|
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.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *PodSpecable) DeepCopyInto(out *PodSpecable) {
|
func (in *PodSpecable) DeepCopyInto(out *PodSpecable) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
|
|
@ -244,7 +244,7 @@ func (r *reporter) ReportReconcile(duration time.Duration, key, success string)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
metrics.Record(ctx, reconcileCountStat.M(1))
|
metrics.RecordBatch(ctx, reconcileCountStat.M(1),
|
||||||
metrics.Record(ctx, reconcileLatencyStat.M(int64(duration/time.Millisecond)))
|
reconcileLatencyStat.M(duration.Milliseconds()))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,15 @@ ${CODEGEN_PKG}/generate-groups.sh "deepcopy" \
|
||||||
|
|
||||||
# Depends on generate-groups.sh to install bin/deepcopy-gen
|
# Depends on generate-groups.sh to install bin/deepcopy-gen
|
||||||
${GOPATH}/bin/deepcopy-gen --input-dirs \
|
${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 \
|
-O zz_generated.deepcopy \
|
||||||
--go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt
|
--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.
|
// Based on the reconcilers we have linked, build up the set of controllers to run.
|
||||||
controllers := make([]*controller.Impl, 0, len(ctors))
|
controllers := make([]*controller.Impl, 0, len(ctors))
|
||||||
webhooks := make([]webhook.AdmissionController, 0)
|
webhooks := make([]interface{}, 0)
|
||||||
for _, cf := range ctors {
|
for _, cf := range ctors {
|
||||||
ctrl := cf(ctx, cmw)
|
ctrl := cf(ctx, cmw)
|
||||||
controllers = append(controllers, ctrl)
|
controllers = append(controllers, ctrl)
|
||||||
|
|
||||||
// Build a list of any reconcilers that implement webhook.AdmissionController
|
// Build a list of any reconcilers that implement webhook.AdmissionController
|
||||||
if ac, ok := ctrl.Reconciler.(webhook.AdmissionController); ok {
|
switch c := ctrl.Reconciler.(type) {
|
||||||
webhooks = append(webhooks, ac)
|
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)
|
wh, err := webhook.New(ctx, webhooks)
|
||||||
if err != nil {
|
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 {
|
eg.Go(func() error {
|
||||||
return wh.Run(ctx.Done())
|
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.
|
// 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) {
|
func CheckLastValueData(t test.T, name string, wantTags map[string]string, wantValue float64) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if row := checkExactlyOneRow(t, name); row != nil {
|
if row := lastRow(t, name); row != nil {
|
||||||
checkRowTags(t, row, name, wantTags)
|
checkRowTags(t, row, name, wantTags)
|
||||||
|
|
||||||
if s, ok := row.Data.(*view.LastValueData); !ok {
|
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 {
|
func checkExactlyOneRow(t test.T, name string) *view.Row {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
d, err := view.RetrieveData(name)
|
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.
|
// URIFromDestinationV1 resolves a v1.Destination into a URL.
|
||||||
func (r *URIResolver) URIFromDestinationV1(dest duckv1.Destination, parent interface{}) (*apis.URL, error) {
|
func (r *URIResolver) URIFromDestinationV1(dest duckv1.Destination, parent interface{}) (*apis.URL, error) {
|
||||||
if dest.Ref != nil {
|
if dest.Ref != nil {
|
||||||
url, err := r.URIFromKnativeReference(dest.Ref, parent)
|
url, err := r.URIFromKReference(dest.Ref, parent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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")
|
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)
|
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: cluster addons to be added to cluster, such as istio
|
||||||
Addons []string
|
Addons []string
|
||||||
|
|
||||||
// EnableWorkloadIdentity: whether to enable Workload Identity -
|
// EnableWorkloadIdentity: whether to enable Workload Identity for this cluster
|
||||||
// https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity or not
|
|
||||||
EnableWorkloadIdentity bool
|
EnableWorkloadIdentity bool
|
||||||
|
|
||||||
|
// ServiceAccount: service account that will be used on this cluster
|
||||||
|
ServiceAccount string
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy will make a deepcopy of the request struct.
|
// DeepCopy will make a deepcopy of the request struct.
|
||||||
|
@ -77,6 +79,7 @@ func (r *Request) DeepCopy() *Request {
|
||||||
Zone: r.Zone,
|
Zone: r.Zone,
|
||||||
Addons: r.Addons,
|
Addons: r.Addons,
|
||||||
EnableWorkloadIdentity: r.EnableWorkloadIdentity,
|
EnableWorkloadIdentity: r.EnableWorkloadIdentity,
|
||||||
|
ServiceAccount: r.ServiceAccount,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,6 +149,12 @@ func NewCreateClusterRequest(request *Request) (*container.CreateClusterRequest,
|
||||||
IdentityNamespace: request.Project + ".svc.id.goog",
|
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.
|
// Manage the GKE cluster version. Only one of initial cluster version or release channel can be specified.
|
||||||
if request.ReleaseChannel != "" {
|
if request.ReleaseChannel != "" {
|
||||||
|
|
|
@ -22,7 +22,9 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
container "google.golang.org/api/container/v1beta1"
|
container "google.golang.org/api/container/v1beta1"
|
||||||
|
|
||||||
"knative.dev/pkg/test/gke"
|
"knative.dev/pkg/test/gke"
|
||||||
"knative.dev/pkg/testutils/clustermanager/e2e-tests/boskos"
|
"knative.dev/pkg/testutils/clustermanager/e2e-tests/boskos"
|
||||||
"knative.dev/pkg/testutils/clustermanager/e2e-tests/common"
|
"knative.dev/pkg/testutils/clustermanager/e2e-tests/common"
|
||||||
|
@ -36,7 +38,6 @@ const (
|
||||||
DefaultGKEZone = ""
|
DefaultGKEZone = ""
|
||||||
regionEnv = "E2E_CLUSTER_REGION"
|
regionEnv = "E2E_CLUSTER_REGION"
|
||||||
backupRegionEnv = "E2E_CLUSTER_BACKUP_REGIONS"
|
backupRegionEnv = "E2E_CLUSTER_BACKUP_REGIONS"
|
||||||
defaultGKEVersion = "latest"
|
|
||||||
DefaultResourceType = boskos.GKEProjectResource
|
DefaultResourceType = boskos.GKEProjectResource
|
||||||
|
|
||||||
ClusterRunning = "RUNNING"
|
ClusterRunning = "RUNNING"
|
||||||
|
@ -231,7 +232,7 @@ func (gc *GKECluster) Acquire() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Creating cluster
|
// 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)
|
err = gc.operations.CreateCluster(gc.Project, region, request.Zone, rb)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cluster, err = gc.operations.GetCluster(gc.Project, region, request.Zone, rb.Cluster.Name)
|
cluster, err = gc.operations.GetCluster(gc.Project, region, request.Zone, rb.Cluster.Name)
|
||||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -41,6 +42,12 @@ const (
|
||||||
statusStopping = "STOPPING"
|
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 {
|
type gkeClient struct {
|
||||||
ops gke.SDKOperations
|
ops gke.SDKOperations
|
||||||
}
|
}
|
||||||
|
@ -237,12 +244,14 @@ func (gc *gkeClient) createClusterWithRetries(gcpProject, name string, config Cl
|
||||||
addons = strings.Split(config.Addons, ",")
|
addons = strings.Split(config.Addons, ",")
|
||||||
}
|
}
|
||||||
req := &gke.Request{
|
req := &gke.Request{
|
||||||
Project: gcpProject,
|
Project: gcpProject,
|
||||||
ClusterName: name,
|
ClusterName: name,
|
||||||
MinNodes: config.NodeCount,
|
MinNodes: config.NodeCount,
|
||||||
MaxNodes: config.NodeCount,
|
MaxNodes: config.NodeCount,
|
||||||
NodeType: config.NodeType,
|
NodeType: config.NodeType,
|
||||||
Addons: addons,
|
Addons: addons,
|
||||||
|
EnableWorkloadIdentity: *enableWorkloadIdentity,
|
||||||
|
ServiceAccount: *serviceAccount,
|
||||||
}
|
}
|
||||||
creq, err := gke.NewCreateClusterRequest(req)
|
creq, err := gke.NewCreateClusterRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -51,7 +51,7 @@ func main() {
|
||||||
case get:
|
case get:
|
||||||
_, err = actions.Get(o)
|
_, err = actions.Get(o)
|
||||||
default:
|
default:
|
||||||
err = errors.New("Must pass one of --create, --delete, --get")
|
err = errors.New("must pass one of --create, --delete, --get")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
metrics.Record(ctx, requestCountM.M(1))
|
metrics.RecordBatch(ctx, requestCountM.M(1),
|
||||||
// Convert time.Duration in nanoseconds to milliseconds
|
// Convert time.Duration in nanoseconds to milliseconds
|
||||||
metrics.Record(ctx, responseTimeInMsecM.M(float64(d/time.Millisecond)))
|
responseTimeInMsecM.M(float64(d.Milliseconds())))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
fakeapixclient "knative.dev/pkg/client/injection/apiextensions/client/fake"
|
||||||
fakekubeclient "knative.dev/pkg/client/injection/kube/client/fake"
|
fakekubeclient "knative.dev/pkg/client/injection/kube/client/fake"
|
||||||
fakedynamicclient "knative.dev/pkg/injection/clients/dynamicclient/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 = logging.WithLogger(ctx, logger)
|
||||||
|
|
||||||
ctx, kubeClient := fakekubeclient.With(ctx, ls.GetKubeObjects()...)
|
ctx, kubeClient := fakekubeclient.With(ctx, ls.GetKubeObjects()...)
|
||||||
|
ctx, apixClient := fakeapixclient.With(ctx, ls.GetApiExtensionsObjects()...)
|
||||||
ctx, dynamicClient := fakedynamicclient.With(ctx,
|
ctx, dynamicClient := fakedynamicclient.With(ctx,
|
||||||
ls.NewScheme(), ToUnstructured(t, ls.NewScheme(), r.Objects)...)
|
ls.NewScheme(), ToUnstructured(t, ls.NewScheme(), r.Objects)...)
|
||||||
|
|
||||||
|
@ -85,6 +87,13 @@ func MakeFactory(ctor Ctor) rtesting.Factory {
|
||||||
return false, nil, nil
|
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.
|
// Set up our Controller from the fakes.
|
||||||
c := ctor(ctx, &ls, configmap.NewStaticWatcher())
|
c := ctor(ctx, &ls, configmap.NewStaticWatcher())
|
||||||
|
@ -93,10 +102,11 @@ func MakeFactory(ctor Ctor) rtesting.Factory {
|
||||||
|
|
||||||
for _, reactor := range r.WithReactors {
|
for _, reactor := range r.WithReactors {
|
||||||
kubeClient.PrependReactor("*", "*", reactor)
|
kubeClient.PrependReactor("*", "*", reactor)
|
||||||
|
apixClient.PrependReactor("*", "*", reactor)
|
||||||
dynamicClient.PrependReactor("*", "*", reactor)
|
dynamicClient.PrependReactor("*", "*", reactor)
|
||||||
}
|
}
|
||||||
|
|
||||||
actionRecorderList := rtesting.ActionRecorderList{dynamicClient, kubeClient}
|
actionRecorderList := rtesting.ActionRecorderList{dynamicClient, kubeClient, apixClient}
|
||||||
eventList := rtesting.EventList{Recorder: eventRecorder}
|
eventList := rtesting.EventList{Recorder: eventRecorder}
|
||||||
|
|
||||||
return c, actionRecorderList, eventList, statsReporter
|
return c, actionRecorderList, eventList, statsReporter
|
||||||
|
|
|
@ -21,9 +21,13 @@ import (
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1"
|
autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1"
|
||||||
corev1 "k8s.io/api/core/v1"
|
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"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
fakekubeclientset "k8s.io/client-go/kubernetes/fake"
|
fakekubeclientset "k8s.io/client-go/kubernetes/fake"
|
||||||
admissionlisters "k8s.io/client-go/listers/admissionregistration/v1beta1"
|
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"
|
appsv1listers "k8s.io/client-go/listers/apps/v1"
|
||||||
autoscalingv2beta1listers "k8s.io/client-go/listers/autoscaling/v2beta1"
|
autoscalingv2beta1listers "k8s.io/client-go/listers/autoscaling/v2beta1"
|
||||||
corev1listers "k8s.io/client-go/listers/core/v1"
|
corev1listers "k8s.io/client-go/listers/core/v1"
|
||||||
|
@ -38,6 +42,7 @@ var clientSetSchemes = []func(*runtime.Scheme) error{
|
||||||
autoscalingv2beta1.AddToScheme,
|
autoscalingv2beta1.AddToScheme,
|
||||||
pkgtesting.AddToScheme,
|
pkgtesting.AddToScheme,
|
||||||
pkgducktesting.AddToScheme,
|
pkgducktesting.AddToScheme,
|
||||||
|
fakeapix.AddToScheme,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listers is used to synthesize informer-style Listers from fixed lists of resources in tests.
|
// 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)
|
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.
|
// GetHorizontalPodAutoscalerLister gets lister for HorizontalPodAutoscaler resources.
|
||||||
func (l *Listers) GetHorizontalPodAutoscalerLister() autoscalingv2beta1listers.HorizontalPodAutoscalerLister {
|
func (l *Listers) GetHorizontalPodAutoscalerLister() autoscalingv2beta1listers.HorizontalPodAutoscalerLister {
|
||||||
return autoscalingv2beta1listers.NewHorizontalPodAutoscalerLister(l.IndexerFor(&autoscalingv2beta1.HorizontalPodAutoscaler{}))
|
return autoscalingv2beta1listers.NewHorizontalPodAutoscalerLister(l.IndexerFor(&autoscalingv2beta1.HorizontalPodAutoscaler{}))
|
||||||
|
@ -137,3 +147,7 @@ func (l *Listers) GetMutatingWebhookConfigurationLister() admissionlisters.Mutat
|
||||||
func (l *Listers) GetValidatingWebhookConfigurationLister() admissionlisters.ValidatingWebhookConfigurationLister {
|
func (l *Listers) GetValidatingWebhookConfigurationLister() admissionlisters.ValidatingWebhookConfigurationLister {
|
||||||
return admissionlisters.NewValidatingWebhookConfigurationLister(l.IndexerFor(&admissionregistrationv1beta1.ValidatingWebhookConfiguration{}))
|
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
|
// New constructs a Webhook
|
||||||
func New(
|
func New(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
controllers []AdmissionController,
|
controllers []interface{},
|
||||||
) (webhook *Webhook, err error) {
|
) (webhook *Webhook, err error) {
|
||||||
|
|
||||||
// ServeMux.Handle panics on duplicate paths
|
// ServeMux.Handle panics on duplicate paths
|
||||||
|
@ -113,15 +113,27 @@ func New(
|
||||||
}
|
}
|
||||||
|
|
||||||
webhook.mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
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 {
|
for _, controller := range controllers {
|
||||||
webhook.mux.Handle(
|
var handler http.Handler
|
||||||
c.Path(),
|
var path string
|
||||||
admissionHandler(logger, opts.StatsReporter, c),
|
|
||||||
)
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue