Repository: knative/pkg
Pull request #2157 (2021-06-15 08:06:10)

Bump k8s min k8s version to 1.19
This patch bumps min k8s version to 1.19

Doc fixes https://github.com/knative/docs/pull/3804.
Please also see https://github.com/knative/community/blob/main/mechanics/RELEASE-VERSIONING-PRINCIPLES.md#knative-serving-version-table

/cc @dprotaso 

knative-prow-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/knative/pkg/pull/2157#" title="Author self-approved">nak3</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **evankanderson** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @evankanderson` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=knative%2Fpkg).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/knative/pkg/blob/main/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["evankanderson"]} -->
codecov[bot]: # [Codecov](https://codecov.io/gh/knative/pkg/pull/2157?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative) Report
> Merging [#2157](https://codecov.io/gh/knative/pkg/pull/2157?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative) (535e58b) into [main](https://codecov.io/gh/knative/pkg/commit/b2bf37c8efc241266f3502eeaf1436efbb95d79f?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative) (b2bf37c) will **decrease** coverage by `0.04%`.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/knative/pkg/pull/2157/graphs/tree.svg?width=650&height=150&src=pr&token=rlqpDnfxbO&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative)](https://codecov.io/gh/knative/pkg/pull/2157?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative)

```diff
@@            Coverage Diff             @@
##             main    #2157      +/-   ##
==========================================
- Coverage   65.90%   65.86%   -0.05%     
==========================================
  Files         221      221              
  Lines        9363     9363              
==========================================
- Hits         6171     6167       -4     
- Misses       2914     2916       +2     
- Partials      278      280       +2     
```


| [Impacted Files](https://codecov.io/gh/knative/pkg/pull/2157?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative) | Coverage Δ | |
|---|---|---|
| [version/version.go](https://codecov.io/gh/knative/pkg/pull/2157/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative#diff-dmVyc2lvbi92ZXJzaW9uLmdv) | `87.50% <ø> (ø)` | |
| [test/gcs/mock/mock.go](https://codecov.io/gh/knative/pkg/pull/2157/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative#diff-dGVzdC9nY3MvbW9jay9tb2NrLmdv) | `90.32% <0.00%> (-2.16%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/knative/pkg/pull/2157?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/knative/pkg/pull/2157?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative). Last update [b2bf37c...535e58b](https://codecov.io/gh/knative/pkg/pull/2157?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative).

knative-prow-robot: @nak3: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-pkg-unit-tests | 535e58b7e302858b6d08531dd48132007bae27cb | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_pkg/2157/pull-knative-pkg-unit-tests/1404711829338329088) | `/test pull-knative-pkg-unit-tests`

[Full PR test history](https://gubernator.knative.dev/pr/knative_pkg/2157). [Your PR dashboard](https://gubernator.knative.dev/pr/nak3).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->

Patch:
diff --git a/apis/duck/v1/knative_reference.go b/apis/duck/v1/knative_reference.go
index 27a0a262b..a0b169d6f 100644
--- a/apis/duck/v1/knative_reference.go
+++ b/apis/duck/v1/knative_reference.go
@@ -19,6 +19,7 @@ package v1
 import (
 	"context"
 	"fmt"
+	"strings"
 
 	"knative.dev/pkg/apis"
 )
@@ -41,7 +42,13 @@ type KReference struct {
 	Name string `json:"name"`
 
 	// API version of the referent.
-	APIVersion string `json:"apiVersion"`
+	// +optional
+	APIVersion string `json:"apiVersion,omitempty"`
+
+	// Group of the API, without the version of the group. This can be used as an alternative to the APIVersion, and then resolved using ResolveGroup.
+	// Note: This API is EXPERIMENTAL and might break anytime. For more details: https://github.com/knative/eventing/issues/5086
+	// +optional
+	Group string `json:"group,omitempty"`
 }
 
 func (kr *KReference) Validate(ctx context.Context) *apis.FieldError {
@@ -54,8 +61,25 @@ func (kr *KReference) Validate(ctx context.Context) *apis.FieldError {
 	if kr.Name == "" {
 		errs = errs.Also(apis.ErrMissingField("name"))
 	}
-	if kr.APIVersion == "" {
-		errs = errs.Also(apis.ErrMissingField("apiVersion"))
+	if isKReferenceGroupAllowed(ctx) {
+		if kr.APIVersion == "" && kr.Group == "" {
+			errs = errs.Also(apis.ErrMissingField("apiVersion")).
+				Also(apis.ErrMissingField("group"))
+		}
+		if kr.APIVersion != "" && kr.Group != "" && !strings.HasPrefix(kr.APIVersion, kr.Group) {
+			errs = errs.Also(&apis.FieldError{
+				Message: "both apiVersion and group are specified and they refer to different API groups",
+				Paths:   []string{"apiVersion", "group"},
+				Details: "Only one of them must be specified",
+			})
+		}
+	} else {
+		if kr.Group != "" {
+			errs = errs.Also(apis.ErrDisallowedFields("group"))
+		}
+		if kr.APIVersion == "" {
+			errs = errs.Also(apis.ErrMissingField("apiVersion"))
+		}
 	}
 	if kr.Kind == "" {
 		errs = errs.Also(apis.ErrMissingField("kind"))
@@ -86,3 +110,17 @@ func (kr *KReference) SetDefaults(ctx context.Context) {
 		kr.Namespace = apis.ParentMeta(ctx).Namespace
 	}
 }
+
+type isGroupAllowed struct{}
+
+func isKReferenceGroupAllowed(ctx context.Context) bool {
+	return ctx.Value(isGroupAllowed{}) != nil
+}
+
+// KReferenceGroupAllowed notes on the context that further validation
+// should allow the KReference.Group, which is disabled by default.
+// Note: This API is EXPERIMENTAL and may disappear once the KReference.Group feature will stabilize.
+// For more details: https://github.com/knative/eventing/issues/5086
+func KReferenceGroupAllowed(ctx context.Context) context.Context {
+	return context.WithValue(ctx, isGroupAllowed{}, struct{}{})
+}
diff --git a/kref/knative_reference.go b/kref/knative_reference.go
new file mode 100644
index 000000000..14f99c4e6
--- /dev/null
+++ b/kref/knative_reference.go
@@ -0,0 +1,77 @@
+/*
+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 kref
+
+import (
+	"fmt"
+
+	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
+	apiextensionsv1lister "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1"
+	"k8s.io/apimachinery/pkg/api/meta"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	duckv1 "knative.dev/pkg/apis/duck/v1"
+)
+
+// KReferenceResolver is an object that resolves the KReference.Group field
+// Note: This API is EXPERIMENTAL and might break anytime. For more details: https://github.com/knative/eventing/issues/5086
+type KReferenceResolver struct {
+	crdLister apiextensionsv1lister.CustomResourceDefinitionLister
+}
+
+// NewKReferenceResolver creates a new KReferenceResolver from a crdLister
+// Note: This API is EXPERIMENTAL and might break anytime. For more details: https://github.com/knative/eventing/issues/5086
+func NewKReferenceResolver(crdLister apiextensionsv1lister.CustomResourceDefinitionLister) *KReferenceResolver {
+	return &KReferenceResolver{crdLister: crdLister}
+}
+
+// ResolveGroup resolves the APIVersion of a KReference starting from the Group.
+// In order to execute this method, you need RBAC to read the CRD of the Resource referred in this KReference.
+// Note: This API is EXPERIMENTAL and might break anytime. For more details: https://github.com/knative/eventing/issues/5086
+func (resolver *KReferenceResolver) ResolveGroup(kr *duckv1.KReference) (*duckv1.KReference, error) {
+	if kr.Group == "" {
+		// Nothing to do here
+		return kr, nil
+	}
+
+	kr = kr.DeepCopy()
+
+	actualGvk := schema.GroupVersionKind{Group: kr.Group, Kind: kr.Kind}
+	pluralGvk, _ := meta.UnsafeGuessKindToResource(actualGvk)
+	crd, err := resolver.crdLister.Get(pluralGvk.GroupResource().String())
+	if err != nil {
+		return nil, err
+	}
+
+	actualGvk.Version, err = findCRDStorageVersion(crd)
+	if err != nil {
+		return nil, err
+	}
+
+	kr.APIVersion, kr.Kind = actualGvk.ToAPIVersionAndKind()
+
+	return kr, nil
+}
+
+// This function runs under the assumption that there must be exactly one "storage" version
+func findCRDStorageVersion(crd *apiextensionsv1.CustomResourceDefinition) (string, error) {
+	for _, version := range crd.Spec.Versions {
+		if version.Storage {
+			return version.Name, nil
+		}
+	}
+	return "", fmt.Errorf("this CRD %s doesn't have a storage version! Kubernetes, you're drunk, go home", crd.Name)
+}
diff --git a/version/version.go b/version/version.go
index e14cbb1b3..86745aacb 100644
--- a/version/version.go
+++ b/version/version.go
@@ -32,9 +32,8 @@ const (
 
 	// NOTE: If you are changing this line, please also update the minimum kubernetes
 	// version listed here:
-	// https://github.com/knative/docs/blob/main/docs/install/any-kubernetes-cluster.md#before-you-begin
-	// https://github.com/knative/docs/blob/main/docs/install/knative-with-operators.md#prerequisites
-	defaultMinimumVersion = "v1.18.0"
+	// https://github.com/knative/docs/blob/mkdocs/docs/snippets/prerequisites.md
+	defaultMinimumVersion = "v1.19.0"
 )
 
 func getMinimumVersion() string {


Test patch:
diff --git a/apis/duck/v1/knative_reference_test.go b/apis/duck/v1/knative_reference_test.go
index 058cb91b3..5af752537 100644
--- a/apis/duck/v1/knative_reference_test.go
+++ b/apis/duck/v1/knative_reference_test.go
@@ -25,6 +25,10 @@ import (
 	"knative.dev/pkg/apis"
 )
 
+const (
+	group = "group.my"
+)
+
 func TestValidate(t *testing.T) {
 	ctx := context.Background()
 
@@ -87,6 +91,71 @@ func TestValidate(t *testing.T) {
 				Details: `parent namespace: "diffns" does not match ref: "b-namespace"`,
 			},
 		},
+		"invalid ref, disallowed group": {
+			ref: &KReference{
+				Namespace: namespace,
+				Name:      name,
+				Kind:      kind,
+				Group:     group,
+			},
+			ctx:  ctx,
+			want: apis.ErrMissingField("apiVersion").Also(apis.ErrDisallowedFields("group")),
+		},
+		"invalid ref, group allowed and both api version and group are specified, but they are conflicting": {
+			ref: &KReference{
+				Namespace:  namespace,
+				Name:       name,
+				Kind:       kind,
+				Group:      group,
+				APIVersion: apiVersion,
+			},
+			ctx: KReferenceGroupAllowed(ctx),
+			want: &apis.FieldError{
+				Message: "both apiVersion and group are specified and they refer to different API groups",
+				Paths:   []string{"apiVersion", "group"},
+				Details: "Only one of them must be specified",
+			},
+		},
+		"invalid ref, group allowed and both api version and group are specified": {
+			ref: &KReference{
+				Namespace:  namespace,
+				Name:       name,
+				Kind:       kind,
+				Group:      "eventing.knative.dev",
+				APIVersion: "eventing.knative.dev/v1",
+			},
+			ctx:  KReferenceGroupAllowed(ctx),
+			want: nil,
+		},
+		"valid ref, group enabled and both apiVersion and group missing": {
+			ref: &KReference{
+				Namespace: namespace,
+				Name:      name,
+				Kind:      kind,
+			},
+			ctx:  KReferenceGroupAllowed(ctx),
+			want: apis.ErrMissingField("apiVersion").Also(apis.ErrMissingField("group")),
+		},
+		"valid ref, group enabled and configured": {
+			ref: &KReference{
+				Namespace: namespace,
+				Name:      name,
+				Kind:      kind,
+				Group:     group,
+			},
+			ctx:  KReferenceGroupAllowed(ctx),
+			want: nil,
+		},
+		"valid ref, group enabled but apiVersion configured": {
+			ref: &KReference{
+				Namespace:  namespace,
+				Name:       name,
+				Kind:       kind,
+				APIVersion: apiVersion,
+			},
+			ctx:  KReferenceGroupAllowed(ctx),
+			want: nil,
+		},
 		"valid ref, mismatched namespaces, but overridden": {
 			ref: &KReference{
 				Namespace:  namespace,
diff --git a/kref/knative_reference_resolve_group_test.go b/kref/knative_reference_resolve_group_test.go
new file mode 100644
index 000000000..ce61e7fa0
--- /dev/null
+++ b/kref/knative_reference_resolve_group_test.go
@@ -0,0 +1,127 @@
+/*
+Copyright 2021 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 kref
+
+import (
+	"context"
+	"testing"
+
+	"github.com/google/go-cmp/cmp"
+	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/client-go/rest"
+
+	. "knative.dev/pkg/apis/duck/v1"
+	customresourcedefinitioninformer "knative.dev/pkg/client/injection/apiextensions/informers/apiextensions/v1/customresourcedefinition/fake"
+	"knative.dev/pkg/injection"
+)
+
+func TestResolveGroup(t *testing.T) {
+	const crdGroup = "messaging.knative.dev"
+	const crdName = "inmemorychannels." + crdGroup
+
+	ctx, _ := injection.Fake.SetupInformers(context.TODO(), &rest.Config{})
+
+	fakeCrdInformer := customresourcedefinitioninformer.Get(ctx)
+	fakeCrdInformer.Informer().GetIndexer().Add(
+		&apiextensionsv1.CustomResourceDefinition{
+			ObjectMeta: metav1.ObjectMeta{
+				Name: crdName,
+			},
+			Spec: apiextensionsv1.CustomResourceDefinitionSpec{
+				Versions: []apiextensionsv1.CustomResourceDefinitionVersion{{
+					Name:    "v1beta1",
+					Storage: false,
+				}, {
+					Name:    "v1",
+					Storage: true,
+				}},
+			},
+		},
+	)
+
+	tests := map[string]struct {
+		input   *KReference
+		output  *KReference
+		wantErr bool
+	}{
+		"No group": {
+			input: &KReference{
+				Kind:       "Abc",
+				Name:       "123",
+				APIVersion: "something/v1",
+			},
+			output: &KReference{
+				Kind:       "Abc",
+				Name:       "123",
+				APIVersion: "something/v1",
+			},
+		},
+		"No group nor api version": {
+			input: &KReference{
+				Kind: "Abc",
+				Name: "123",
+			},
+			output: &KReference{
+				Kind: "Abc",
+				Name: "123",
+			},
+		},
+		"imc channel": {
+			input: &KReference{
+				Kind:  "InMemoryChannel",
+				Name:  "my-cool-channel",
+				Group: crdGroup,
+			},
+			output: &KReference{
+				Kind:       "InMemoryChannel",
+				Name:       "my-cool-channel",
+				Group:      crdGroup,
+				APIVersion: crdGroup + "/v1",
+			},
+		},
+		"unknown CRD": {
+			input: &KReference{
+				Kind:  "MyChannel",
+				Name:  "my-cool-channel",
+				Group: crdGroup,
+			},
+			wantErr: true,
+		},
+	}
+
+	for name, tc := range tests {
+		t.Run(name, func(t *testing.T) {
+			kr, err := NewKReferenceResolver(fakeCrdInformer.Lister()).ResolveGroup(tc.input)
+			if err != nil {
+				if !tc.wantErr {
+					t.Error("ResolveGroup() =", err)
+				}
+				return
+			} else if tc.wantErr {
+				t.Errorf("ResolveGroup() = %v, wanted error", err)
+				return
+			}
+
+			if tc.output != nil {
+				if !cmp.Equal(tc.output, kr) {
+					t.Errorf("ResolveGroup diff: (-want, +got) =\n%s", cmp.Diff(tc.input, tc.output))
+				}
+			}
+		})
+	}
+}
diff --git a/version/version_test.go b/version/version_test.go
index 2080dbc3b..76eaeda0f 100644
--- a/version/version_test.go
+++ b/version/version_test.go
@@ -41,13 +41,13 @@ func TestVersionCheck(t *testing.T) {
 		wantError       bool
 	}{{
 		name:          "greater version (patch)",
-		actualVersion: &testVersioner{version: "v1.18.2"},
+		actualVersion: &testVersioner{version: "v1.19.2"},
 	}, {
 		name:          "greater version (patch), no v",
-		actualVersion: &testVersioner{version: "1.18.2"},
+		actualVersion: &testVersioner{version: "1.19.2"},
 	}, {
 		name:          "greater version (patch), pre-release",
-		actualVersion: &testVersioner{version: "1.18.2-kpn-065dce"},
+		actualVersion: &testVersioner{version: "1.19.2-kpn-065dce"},
 	}, {
 		name:            "greater version (patch), pre-release, envvar override",
 		actualVersion:   &testVersioner{version: "1.15.11-kpn-065dce"},
@@ -58,16 +58,16 @@ func TestVersionCheck(t *testing.T) {
 		versionOverride: "1.15.11-0",
 	}, {
 		name:          "greater version (minor)",
-		actualVersion: &testVersioner{version: "v1.18.0"},
+		actualVersion: &testVersioner{version: "v1.19.0"},
 	}, {
 		name:          "same version",
-		actualVersion: &testVersioner{version: "v1.18.0"},
+		actualVersion: &testVersioner{version: "v1.19.0"},
 	}, {
 		name:          "same version with build",
-		actualVersion: &testVersioner{version: "v1.18.0+k3s.1"},
+		actualVersion: &testVersioner{version: "v1.19.0+k3s.1"},
 	}, {
 		name:          "same version with pre-release",
-		actualVersion: &testVersioner{version: "v1.18.0-k3s.1"},
+		actualVersion: &testVersioner{version: "v1.19.0-k3s.1"},
 	}, {
 		name:          "smaller version",
 		actualVersion: &testVersioner{version: "v1.14.3"},