mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 22:46:12 +00:00
Merge pull request #99101 from deads2k/crd-beta-prune
stop using CRD v1beta1 in tests
This commit is contained in:
commit
2f263b24a7
@ -21,7 +21,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
@ -34,43 +34,50 @@ func TestAPIApproval(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if noxuAPIApproved := findCRDCondition(noxuDefinition, apiextensionsv1beta1.KubernetesAPIApprovalPolicyConformant); noxuAPIApproved != nil {
|
if noxuAPIApproved := findCRDCondition(noxuDefinition, apiextensionsv1.KubernetesAPIApprovalPolicyConformant); noxuAPIApproved != nil {
|
||||||
t.Fatal(noxuAPIApproved)
|
t.Fatal(noxuAPIApproved)
|
||||||
}
|
}
|
||||||
|
|
||||||
newSigKubeAPIFn := func(resource, approvalAnnotation string) *apiextensionsv1beta1.CustomResourceDefinition {
|
newSigKubeAPIFn := func(resource, approvalAnnotation string) *apiextensionsv1.CustomResourceDefinition {
|
||||||
return &apiextensionsv1beta1.CustomResourceDefinition{
|
return &apiextensionsv1.CustomResourceDefinition{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: resource + ".sigs.k8s.io", Annotations: map[string]string{apiextensionsv1beta1.KubeAPIApprovedAnnotation: approvalAnnotation}},
|
ObjectMeta: metav1.ObjectMeta{Name: resource + ".sigs.k8s.io", Annotations: map[string]string{apiextensionsv1.KubeAPIApprovedAnnotation: approvalAnnotation}},
|
||||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||||
Group: "sigs.k8s.io",
|
Group: "sigs.k8s.io",
|
||||||
Version: "v1beta1",
|
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
{
|
||||||
|
Name: "v1beta1",
|
||||||
|
Served: true,
|
||||||
|
Storage: true,
|
||||||
|
Schema: fixtures.AllowAllSchema(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||||
Plural: resource,
|
Plural: resource,
|
||||||
Singular: resource + "singular",
|
Singular: resource + "singular",
|
||||||
Kind: resource + "Kind",
|
Kind: resource + "Kind",
|
||||||
ListKind: resource + "List",
|
ListKind: resource + "List",
|
||||||
},
|
},
|
||||||
Scope: apiextensionsv1beta1.NamespaceScoped,
|
Scope: apiextensionsv1.NamespaceScoped,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// the unit tests cover all variations. We just need to be sure that we see the code being called
|
// the unit tests cover all variations. We just need to be sure that we see the code being called
|
||||||
approvedKubeAPI := newSigKubeAPIFn("approved", "https://github.com/kubernetes/kubernetes/pull/79724")
|
approvedKubeAPI := newSigKubeAPIFn("approved", "https://github.com/kubernetes/kubernetes/pull/79724")
|
||||||
approvedKubeAPI, err = fixtures.CreateNewCustomResourceDefinition(approvedKubeAPI, apiExtensionClient, dynamicClient)
|
approvedKubeAPI, err = fixtures.CreateNewV1CustomResourceDefinition(approvedKubeAPI, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, func() (bool, error) {
|
err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, func() (bool, error) {
|
||||||
approvedKubeAPI, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), approvedKubeAPI.Name, metav1.GetOptions{})
|
approvedKubeAPI, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), approvedKubeAPI.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
if approvedKubeAPIApproved := findCRDCondition(approvedKubeAPI, apiextensionsv1beta1.KubernetesAPIApprovalPolicyConformant); approvedKubeAPIApproved == nil || approvedKubeAPIApproved.Status != apiextensionsv1beta1.ConditionTrue {
|
if approvedKubeAPIApproved := findCRDCondition(approvedKubeAPI, apiextensionsv1.KubernetesAPIApprovalPolicyConformant); approvedKubeAPIApproved == nil || approvedKubeAPIApproved.Status != apiextensionsv1.ConditionTrue {
|
||||||
t.Log(approvedKubeAPIApproved)
|
t.Log(approvedKubeAPIApproved)
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
@ -50,14 +50,14 @@ func TestApplyBasic(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
kind := noxuDefinition.Spec.Names.Kind
|
kind := noxuDefinition.Spec.Names.Kind
|
||||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Version
|
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name
|
||||||
|
|
||||||
rest := apiExtensionClient.Discovery().RESTClient()
|
rest := apiExtensionClient.Discovery().RESTClient()
|
||||||
yamlBody := []byte(fmt.Sprintf(`
|
yamlBody := []byte(fmt.Sprintf(`
|
||||||
@ -70,7 +70,7 @@ values:
|
|||||||
boolVal: true
|
boolVal: true
|
||||||
stringVal: "1"`, apiVersion, kind))
|
stringVal: "1"`, apiVersion, kind))
|
||||||
result, err := rest.Patch(types.ApplyPatchType).
|
result, err := rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Name("mytest").
|
Name("mytest").
|
||||||
Param("fieldManager", "apply_test").
|
Param("fieldManager", "apply_test").
|
||||||
Body(yamlBody).
|
Body(yamlBody).
|
||||||
@ -80,7 +80,7 @@ values:
|
|||||||
}
|
}
|
||||||
|
|
||||||
result, err = rest.Patch(types.MergePatchType).
|
result, err = rest.Patch(types.MergePatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Name("mytest").
|
Name("mytest").
|
||||||
Body([]byte(`{"values":{"numVal": 5}}`)).
|
Body([]byte(`{"values":{"numVal": 5}}`)).
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
@ -90,7 +90,7 @@ values:
|
|||||||
|
|
||||||
// Re-apply the same object, we should get conflicts now.
|
// Re-apply the same object, we should get conflicts now.
|
||||||
result, err = rest.Patch(types.ApplyPatchType).
|
result, err = rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Name("mytest").
|
Name("mytest").
|
||||||
Param("fieldManager", "apply_test").
|
Param("fieldManager", "apply_test").
|
||||||
Body(yamlBody).
|
Body(yamlBody).
|
||||||
@ -108,7 +108,7 @@ values:
|
|||||||
|
|
||||||
// Re-apply with force, should work fine.
|
// Re-apply with force, should work fine.
|
||||||
result, err = rest.Patch(types.ApplyPatchType).
|
result, err = rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Name("mytest").
|
Name("mytest").
|
||||||
Param("force", "true").
|
Param("force", "true").
|
||||||
Param("fieldManager", "apply_test").
|
Param("fieldManager", "apply_test").
|
||||||
|
@ -25,7 +25,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/api/meta"
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
@ -56,8 +56,8 @@ func TestNamespaceScopedCRUD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -75,8 +75,8 @@ func TestClusterScopedCRUD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ func TestClusterScopedCRUD(t *testing.T) {
|
|||||||
testFieldSelector(t, ns, noxuDefinition, dynamicClient)
|
testFieldSelector(t, ns, noxuDefinition, dynamicClient)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSimpleCRUD(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition, dynamicClient dynamic.Interface) {
|
func testSimpleCRUD(t *testing.T, ns string, noxuDefinition *apiextensionsv1.CustomResourceDefinition, dynamicClient dynamic.Interface) {
|
||||||
noxuResourceClients := map[string]dynamic.ResourceInterface{}
|
noxuResourceClients := map[string]dynamic.ResourceInterface{}
|
||||||
noxuWatchs := map[string]watch.Interface{}
|
noxuWatchs := map[string]watch.Interface{}
|
||||||
disabledVersions := map[string]bool{}
|
disabledVersions := map[string]bool{}
|
||||||
@ -321,8 +321,8 @@ func TestInvalidCRUD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -373,7 +373,7 @@ func TestInvalidCRUD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testFieldSelector(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition, dynamicClient dynamic.Interface) {
|
func testFieldSelector(t *testing.T, ns string, noxuDefinition *apiextensionsv1.CustomResourceDefinition, dynamicClient dynamic.Interface) {
|
||||||
noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
|
noxuResourceClient := newNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
|
||||||
initialList, err := noxuResourceClient.List(context.TODO(), metav1.ListOptions{})
|
initialList, err := noxuResourceClient.List(context.TODO(), metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -527,9 +527,9 @@ func TestDiscovery(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
scope := apiextensionsv1beta1.NamespaceScoped
|
scope := apiextensionsv1.NamespaceScoped
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(scope)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(scope)
|
||||||
if _, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient); err != nil {
|
if _, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -574,8 +574,8 @@ func TestNoNamespaceReject(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -593,7 +593,7 @@ func TestNoNamespaceReject(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Version, initialListTypeMeta.GetAPIVersion(); e != a {
|
if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Versions[0].Name, initialListTypeMeta.GetAPIVersion(); e != a {
|
||||||
t.Errorf("expected %v, got %v", e, a)
|
t.Errorf("expected %v, got %v", e, a)
|
||||||
}
|
}
|
||||||
if e, a := noxuDefinition.Spec.Names.ListKind, initialListTypeMeta.GetKind(); e != a {
|
if e, a := noxuDefinition.Spec.Names.ListKind, initialListTypeMeta.GetKind(); e != a {
|
||||||
@ -613,8 +613,8 @@ func TestSameNameDiffNamespace(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -636,8 +636,8 @@ func TestSelfLink(t *testing.T) {
|
|||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
// namespace scoped
|
// namespace scoped
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -656,8 +656,8 @@ func TestSelfLink(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cluster scoped
|
// cluster scoped
|
||||||
curletDefinition := fixtures.NewCurletCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
curletDefinition := fixtures.NewCurletV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||||
curletDefinition, err = fixtures.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient)
|
curletDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -682,8 +682,8 @@ func TestPreserveInt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -724,8 +724,8 @@ func TestPatch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -802,8 +802,8 @@ func TestCrossNamespaceListWatch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -881,7 +881,7 @@ func TestCrossNamespaceListWatch(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Version, createdTypeMeta.GetAPIVersion(); e != a {
|
if e, a := noxuDefinition.Spec.Group+"/"+noxuDefinition.Spec.Versions[0].Name, createdTypeMeta.GetAPIVersion(); e != a {
|
||||||
t.Errorf("expected %v, got %v", e, a)
|
t.Errorf("expected %v, got %v", e, a)
|
||||||
}
|
}
|
||||||
if e, a := noxuDefinition.Spec.Names.Kind, createdTypeMeta.GetKind(); e != a {
|
if e, a := noxuDefinition.Spec.Names.Kind, createdTypeMeta.GetKind(); e != a {
|
||||||
@ -901,7 +901,7 @@ func TestCrossNamespaceListWatch(t *testing.T) {
|
|||||||
checkNamespacesWatchHelper(t, ns2, noxuNamespacesWatch2)
|
checkNamespacesWatchHelper(t, ns2, noxuNamespacesWatch2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createInstanceWithNamespaceHelper(t *testing.T, ns string, name string, noxuNamespacedResourceClient dynamic.ResourceInterface, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition) *unstructured.Unstructured {
|
func createInstanceWithNamespaceHelper(t *testing.T, ns string, name string, noxuNamespacedResourceClient dynamic.ResourceInterface, noxuDefinition *apiextensionsv1.CustomResourceDefinition) *unstructured.Unstructured {
|
||||||
createdInstance, err := instantiateCustomResource(t, fixtures.NewNoxuInstance(ns, name), noxuNamespacedResourceClient, noxuDefinition)
|
createdInstance, err := instantiateCustomResource(t, fixtures.NewNoxuInstance(ns, name), noxuNamespacedResourceClient, noxuDefinition)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create noxu Instance:%v", err)
|
t.Fatalf("unable to create noxu Instance:%v", err)
|
||||||
@ -944,27 +944,27 @@ func TestNameConflict(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
noxu2Definition := fixtures.NewNoxu2CustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
noxu2Definition := fixtures.NewNoxu2CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||||
_, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Create(context.TODO(), noxu2Definition, metav1.CreateOptions{})
|
_, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Create(context.TODO(), noxu2Definition, metav1.CreateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A NameConflict occurs
|
// A NameConflict occurs
|
||||||
err = wait.Poll(500*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) {
|
err = wait.Poll(500*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) {
|
||||||
crd, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), noxu2Definition.Name, metav1.GetOptions{})
|
crd, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxu2Definition.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, condition := range crd.Status.Conditions {
|
for _, condition := range crd.Status.Conditions {
|
||||||
if condition.Type == apiextensionsv1beta1.NamesAccepted && condition.Status == apiextensionsv1beta1.ConditionFalse {
|
if condition.Type == apiextensionsv1.NamesAccepted && condition.Status == apiextensionsv1.ConditionFalse {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -974,20 +974,20 @@ func TestNameConflict(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient)
|
err = fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Names are now accepted
|
// Names are now accepted
|
||||||
err = wait.Poll(500*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) {
|
err = wait.Poll(500*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) {
|
||||||
crd, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), noxu2Definition.Name, metav1.GetOptions{})
|
crd, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxu2Definition.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, condition := range crd.Status.Conditions {
|
for _, condition := range crd.Status.Conditions {
|
||||||
if condition.Type == apiextensionsv1beta1.NamesAccepted && condition.Status == apiextensionsv1beta1.ConditionTrue {
|
if condition.Type == apiextensionsv1.NamesAccepted && condition.Status == apiextensionsv1.ConditionTrue {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1005,15 +1005,15 @@ func TestStatusGetAndPatch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure we don't get 405 Method Not Allowed from Getting CRD/status subresource
|
// make sure we don't get 405 Method Not Allowed from Getting CRD/status subresource
|
||||||
result := &apiextensionsv1beta1.CustomResourceDefinition{}
|
result := &apiextensionsv1.CustomResourceDefinition{}
|
||||||
err = apiExtensionClient.ApiextensionsV1beta1().RESTClient().Get().
|
err = apiExtensionClient.ApiextensionsV1().RESTClient().Get().
|
||||||
Resource("customresourcedefinitions").
|
Resource("customresourcedefinitions").
|
||||||
Name(noxuDefinition.Name).
|
Name(noxuDefinition.Name).
|
||||||
SubResource("status").
|
SubResource("status").
|
||||||
@ -1024,7 +1024,7 @@ func TestStatusGetAndPatch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// make sure we don't get 405 Method Not Allowed from Patching CRD/status subresource
|
// make sure we don't get 405 Method Not Allowed from Patching CRD/status subresource
|
||||||
_, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().
|
_, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().
|
||||||
Patch(context.TODO(), noxuDefinition.Name, types.StrategicMergePatchType,
|
Patch(context.TODO(), noxuDefinition.Name, types.StrategicMergePatchType,
|
||||||
[]byte(fmt.Sprintf(`{"labels":{"test-label":"dummy"}}`)), metav1.PatchOptions{},
|
[]byte(fmt.Sprintf(`{"labels":{"test-label":"dummy"}}`)), metav1.PatchOptions{},
|
||||||
"status")
|
"status")
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
@ -50,8 +50,8 @@ func TestChangeCRD(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionsClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionsClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ func TestChangeCRD(t *testing.T) {
|
|||||||
|
|
||||||
time.Sleep(10 * time.Millisecond)
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
|
||||||
noxuDefinitionToUpdate, err := apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{})
|
noxuDefinitionToUpdate, err := apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
continue
|
continue
|
||||||
@ -90,7 +90,7 @@ func TestChangeCRD(t *testing.T) {
|
|||||||
} else {
|
} else {
|
||||||
noxuDefinitionToUpdate.Spec.Versions = noxuDefinitionToUpdate.Spec.Versions[0:1]
|
noxuDefinitionToUpdate.Spec.Versions = noxuDefinitionToUpdate.Spec.Versions[0:1]
|
||||||
}
|
}
|
||||||
if _, err := apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), noxuDefinitionToUpdate, metav1.UpdateOptions{}); err != nil && !apierrors.IsConflict(err) {
|
if _, err := apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), noxuDefinitionToUpdate, metav1.UpdateOptions{}); err != nil && !apierrors.IsConflict(err) {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -335,10 +335,8 @@ func validateNonTrivialConverted(t *testing.T, ctc *conversionTestContext) {
|
|||||||
client := ctc.versionedClient(ns, createVersion.Name)
|
client := ctc.versionedClient(ns, createVersion.Name)
|
||||||
|
|
||||||
fixture := newConversionMultiVersionFixture(ns, name, createVersion.Name)
|
fixture := newConversionMultiVersionFixture(ns, name, createVersion.Name)
|
||||||
if !*ctc.crd.Spec.PreserveUnknownFields {
|
if err := unstructured.SetNestedField(fixture.Object, "foo", "garbage"); err != nil {
|
||||||
if err := unstructured.SetNestedField(fixture.Object, "foo", "garbage"); err != nil {
|
t.Fatal(err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if _, err := client.Create(context.TODO(), fixture, metav1.CreateOptions{}); err != nil {
|
if _, err := client.Create(context.TODO(), fixture, metav1.CreateOptions{}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -393,10 +391,8 @@ func validateNonTrivialConvertedList(t *testing.T, ctc *conversionTestContext) {
|
|||||||
name := "converted-" + createVersion.Name
|
name := "converted-" + createVersion.Name
|
||||||
client := ctc.versionedClient(ns, createVersion.Name)
|
client := ctc.versionedClient(ns, createVersion.Name)
|
||||||
fixture := newConversionMultiVersionFixture(ns, name, createVersion.Name)
|
fixture := newConversionMultiVersionFixture(ns, name, createVersion.Name)
|
||||||
if !*ctc.crd.Spec.PreserveUnknownFields {
|
if err := unstructured.SetNestedField(fixture.Object, "foo", "garbage"); err != nil {
|
||||||
if err := unstructured.SetNestedField(fixture.Object, "foo", "garbage"); err != nil {
|
t.Fatal(err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_, err := client.Create(context.TODO(), fixture, metav1.CreateOptions{})
|
_, err := client.Create(context.TODO(), fixture, metav1.CreateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -428,10 +424,6 @@ func validateNonTrivialConvertedList(t *testing.T, ctc *conversionTestContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func validateStoragePruning(t *testing.T, ctc *conversionTestContext) {
|
func validateStoragePruning(t *testing.T, ctc *conversionTestContext) {
|
||||||
if *ctc.crd.Spec.PreserveUnknownFields {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ns := ctc.namespace
|
ns := ctc.namespace
|
||||||
|
|
||||||
for _, createVersion := range ctc.crd.Spec.Versions {
|
for _, createVersion := range ctc.crd.Spec.Versions {
|
||||||
@ -905,13 +897,13 @@ func newConversionTestContext(t *testing.T, apiExtensionsClient clientset.Interf
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
crd, err := apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), v1CRD.Name, metav1.GetOptions{})
|
crd, err := apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), v1CRD.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tearDown := func() {
|
tearDown := func() {
|
||||||
if err := fixtures.DeleteCustomResourceDefinition(crd, apiExtensionsClient); err != nil {
|
if err := fixtures.DeleteV1CustomResourceDefinition(crd, apiExtensionsClient); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -923,13 +915,13 @@ type conversionTestContext struct {
|
|||||||
namespace string
|
namespace string
|
||||||
apiExtensionsClient clientset.Interface
|
apiExtensionsClient clientset.Interface
|
||||||
dynamicClient dynamic.Interface
|
dynamicClient dynamic.Interface
|
||||||
crd *apiextensionsv1beta1.CustomResourceDefinition
|
crd *apiextensionsv1.CustomResourceDefinition
|
||||||
etcdObjectReader *storage.EtcdObjectReader
|
etcdObjectReader *storage.EtcdObjectReader
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *conversionTestContext) versionedClient(ns string, version string) dynamic.ResourceInterface {
|
func (c *conversionTestContext) versionedClient(ns string, version string) dynamic.ResourceInterface {
|
||||||
gvr := schema.GroupVersionResource{Group: c.crd.Spec.Group, Version: version, Resource: c.crd.Spec.Names.Plural}
|
gvr := schema.GroupVersionResource{Group: c.crd.Spec.Group, Version: version, Resource: c.crd.Spec.Names.Plural}
|
||||||
if c.crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped {
|
if c.crd.Spec.Scope != apiextensionsv1.ClusterScoped {
|
||||||
return c.dynamicClient.Resource(gvr).Namespace(ns)
|
return c.dynamicClient.Resource(gvr).Namespace(ns)
|
||||||
}
|
}
|
||||||
return c.dynamicClient.Resource(gvr)
|
return c.dynamicClient.Resource(gvr)
|
||||||
@ -943,17 +935,19 @@ func (c *conversionTestContext) versionedClients(ns string) map[string]dynamic.R
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *conversionTestContext) setConversionWebhook(t *testing.T, webhookClientConfig *apiextensionsv1beta1.WebhookClientConfig, reviewVersions []string) {
|
func (c *conversionTestContext) setConversionWebhook(t *testing.T, webhookClientConfig *apiextensionsv1.WebhookClientConfig, reviewVersions []string) {
|
||||||
crd, err := c.apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), c.crd.Name, metav1.GetOptions{})
|
crd, err := c.apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), c.crd.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
crd.Spec.Conversion = &apiextensionsv1beta1.CustomResourceConversion{
|
crd.Spec.Conversion = &apiextensionsv1.CustomResourceConversion{
|
||||||
Strategy: apiextensionsv1beta1.WebhookConverter,
|
Strategy: apiextensionsv1.WebhookConverter,
|
||||||
WebhookClientConfig: webhookClientConfig,
|
Webhook: &apiextensionsv1.WebhookConversion{
|
||||||
ConversionReviewVersions: reviewVersions,
|
ClientConfig: webhookClientConfig,
|
||||||
|
ConversionReviewVersions: reviewVersions,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
crd, err = c.apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{})
|
crd, err = c.apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -962,15 +956,15 @@ func (c *conversionTestContext) setConversionWebhook(t *testing.T, webhookClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *conversionTestContext) removeConversionWebhook(t *testing.T) {
|
func (c *conversionTestContext) removeConversionWebhook(t *testing.T) {
|
||||||
crd, err := c.apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), c.crd.Name, metav1.GetOptions{})
|
crd, err := c.apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), c.crd.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
crd.Spec.Conversion = &apiextensionsv1beta1.CustomResourceConversion{
|
crd.Spec.Conversion = &apiextensionsv1.CustomResourceConversion{
|
||||||
Strategy: apiextensionsv1beta1.NoneConverter,
|
Strategy: apiextensionsv1.NoneConverter,
|
||||||
}
|
}
|
||||||
|
|
||||||
crd, err = c.apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{})
|
crd, err = c.apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -998,14 +992,14 @@ func (c *conversionTestContext) setAndWaitStorageVersion(t *testing.T, version s
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *conversionTestContext) setStorageVersion(t *testing.T, version string) {
|
func (c *conversionTestContext) setStorageVersion(t *testing.T, version string) {
|
||||||
crd, err := c.apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), c.crd.Name, metav1.GetOptions{})
|
crd, err := c.apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), c.crd.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
for i, v := range crd.Spec.Versions {
|
for i, v := range crd.Spec.Versions {
|
||||||
crd.Spec.Versions[i].Storage = v.Name == version
|
crd.Spec.Versions[i].Storage = v.Name == version
|
||||||
}
|
}
|
||||||
crd, err = c.apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{})
|
crd, err = c.apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -1027,7 +1021,7 @@ func (c *conversionTestContext) waitForStorageVersion(t *testing.T, version stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *conversionTestContext) setServed(t *testing.T, version string, served bool) {
|
func (c *conversionTestContext) setServed(t *testing.T, version string, served bool) {
|
||||||
crd, err := c.apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), c.crd.Name, metav1.GetOptions{})
|
crd, err := c.apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), c.crd.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -1036,7 +1030,7 @@ func (c *conversionTestContext) setServed(t *testing.T, version string, served b
|
|||||||
crd.Spec.Versions[i].Served = served
|
crd.Spec.Versions[i].Served = served
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
crd, err = c.apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{})
|
crd, err = c.apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ import (
|
|||||||
|
|
||||||
// StartConversionWebhookServer starts an http server with the provided handler and returns the WebhookClientConfig
|
// StartConversionWebhookServer starts an http server with the provided handler and returns the WebhookClientConfig
|
||||||
// needed to configure a CRD to use this conversion webhook as its converter.
|
// needed to configure a CRD to use this conversion webhook as its converter.
|
||||||
func StartConversionWebhookServer(handler http.Handler) (func(), *apiextensionsv1beta1.WebhookClientConfig, error) {
|
func StartConversionWebhookServer(handler http.Handler) (func(), *apiextensionsv1.WebhookClientConfig, error) {
|
||||||
roots := x509.NewCertPool()
|
roots := x509.NewCertPool()
|
||||||
if !roots.AppendCertsFromPEM(localhostCert) {
|
if !roots.AppendCertsFromPEM(localhostCert) {
|
||||||
return nil, nil, fmt.Errorf("failed to append Cert from PEM")
|
return nil, nil, fmt.Errorf("failed to append Cert from PEM")
|
||||||
@ -57,7 +57,7 @@ func StartConversionWebhookServer(handler http.Handler) (func(), *apiextensionsv
|
|||||||
}
|
}
|
||||||
webhookServer.StartTLS()
|
webhookServer.StartTLS()
|
||||||
endpoint := webhookServer.URL + "/convert"
|
endpoint := webhookServer.URL + "/convert"
|
||||||
webhookConfig := &apiextensionsv1beta1.WebhookClientConfig{
|
webhookConfig := &apiextensionsv1.WebhookClientConfig{
|
||||||
CABundle: localhostCert,
|
CABundle: localhostCert,
|
||||||
URL: &endpoint,
|
URL: &endpoint,
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,7 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
|
|
||||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
@ -36,8 +35,8 @@ func TestFinalization(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ns := "not-the-default"
|
ns := "not-the-default"
|
||||||
@ -100,8 +99,8 @@ func TestFinalizationAndDeletion(t *testing.T) {
|
|||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
// Create a CRD.
|
// Create a CRD.
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Create a CR with a finalizer.
|
// Create a CR with a finalizer.
|
||||||
@ -129,7 +128,7 @@ func TestFinalizationAndDeletion(t *testing.T) {
|
|||||||
require.NotNil(t, gottenNoxuInstance.GetDeletionTimestamp())
|
require.NotNil(t, gottenNoxuInstance.GetDeletionTimestamp())
|
||||||
|
|
||||||
// Delete the CRD.
|
// Delete the CRD.
|
||||||
fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient)
|
fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient)
|
||||||
|
|
||||||
// Check is CR still there after the CRD deletion.
|
// Check is CR still there after the CRD deletion.
|
||||||
gottenNoxuInstance, err = noxuResourceClient.Get(context.TODO(), name, metav1.GetOptions{})
|
gottenNoxuInstance, err = noxuResourceClient.Get(context.TODO(), name, metav1.GetOptions{})
|
||||||
@ -157,7 +156,7 @@ func TestFinalizationAndDeletion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = wait.Poll(500*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) {
|
err = wait.Poll(500*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) {
|
||||||
_, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{})
|
_, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{})
|
||||||
return errors.IsNotFound(err), err
|
return errors.IsNotFound(err), err
|
||||||
})
|
})
|
||||||
if !errors.IsNotFound(err) {
|
if !errors.IsNotFound(err) {
|
||||||
|
@ -44,6 +44,16 @@ const (
|
|||||||
noxuInstanceNum int64 = 9223372036854775807
|
noxuInstanceNum int64 = 9223372036854775807
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// AllowAllSchema doesn't enforce any schema restrictions
|
||||||
|
func AllowAllSchema() *apiextensionsv1.CustomResourceValidation {
|
||||||
|
return &apiextensionsv1.CustomResourceValidation{
|
||||||
|
OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{
|
||||||
|
XPreserveUnknownFields: pointer.BoolPtr(true),
|
||||||
|
Type: "object",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewRandomNameV1CustomResourceDefinition generates a CRD with random name to avoid name conflict in e2e tests
|
// NewRandomNameV1CustomResourceDefinition generates a CRD with random name to avoid name conflict in e2e tests
|
||||||
func NewRandomNameV1CustomResourceDefinition(scope apiextensionsv1.ResourceScope) *apiextensionsv1.CustomResourceDefinition {
|
func NewRandomNameV1CustomResourceDefinition(scope apiextensionsv1.ResourceScope) *apiextensionsv1.CustomResourceDefinition {
|
||||||
// ensure the singular doesn't end in an s for now
|
// ensure the singular doesn't end in an s for now
|
||||||
@ -57,12 +67,7 @@ func NewRandomNameV1CustomResourceDefinition(scope apiextensionsv1.ResourceScope
|
|||||||
Name: "v1beta1",
|
Name: "v1beta1",
|
||||||
Served: true,
|
Served: true,
|
||||||
Storage: true,
|
Storage: true,
|
||||||
Schema: &apiextensionsv1.CustomResourceValidation{
|
Schema: AllowAllSchema(),
|
||||||
OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{
|
|
||||||
XPreserveUnknownFields: pointer.BoolPtr(true),
|
|
||||||
Type: "object",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||||
@ -76,46 +81,6 @@ func NewRandomNameV1CustomResourceDefinition(scope apiextensionsv1.ResourceScope
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRandomNameCustomResourceDefinition generates a CRD with random name to avoid name conflict in e2e tests
|
|
||||||
func NewRandomNameCustomResourceDefinition(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition {
|
|
||||||
// ensure the singular doesn't end in an s for now
|
|
||||||
gName := names.SimpleNameGenerator.GenerateName("foo") + "a"
|
|
||||||
return &apiextensionsv1beta1.CustomResourceDefinition{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: gName + "s.mygroup.example.com"},
|
|
||||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
|
||||||
Group: "mygroup.example.com",
|
|
||||||
Version: "v1beta1",
|
|
||||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
|
||||||
Plural: gName + "s",
|
|
||||||
Singular: gName,
|
|
||||||
Kind: gName,
|
|
||||||
ListKind: gName + "List",
|
|
||||||
},
|
|
||||||
Scope: scope,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNoxuCustomResourceDefinition returns a WishIHadChosenNoxu CRD.
|
|
||||||
func NewNoxuCustomResourceDefinition(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition {
|
|
||||||
return &apiextensionsv1beta1.CustomResourceDefinition{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"},
|
|
||||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
|
||||||
Group: "mygroup.example.com",
|
|
||||||
Version: "v1beta1",
|
|
||||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
|
||||||
Plural: "noxus",
|
|
||||||
Singular: "nonenglishnoxu",
|
|
||||||
Kind: "WishIHadChosenNoxu",
|
|
||||||
ShortNames: []string{"foo", "bar", "abc", "def"},
|
|
||||||
ListKind: "NoxuItemList",
|
|
||||||
Categories: []string{"all"},
|
|
||||||
},
|
|
||||||
Scope: scope,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNoxuV1CustomResourceDefinition returns a WishIHadChosenNoxu CRD.
|
// NewNoxuV1CustomResourceDefinition returns a WishIHadChosenNoxu CRD.
|
||||||
func NewNoxuV1CustomResourceDefinition(scope apiextensionsv1.ResourceScope) *apiextensionsv1.CustomResourceDefinition {
|
func NewNoxuV1CustomResourceDefinition(scope apiextensionsv1.ResourceScope) *apiextensionsv1.CustomResourceDefinition {
|
||||||
return &apiextensionsv1.CustomResourceDefinition{
|
return &apiextensionsv1.CustomResourceDefinition{
|
||||||
@ -126,12 +91,7 @@ func NewNoxuV1CustomResourceDefinition(scope apiextensionsv1.ResourceScope) *api
|
|||||||
Name: "v1beta1",
|
Name: "v1beta1",
|
||||||
Served: true,
|
Served: true,
|
||||||
Storage: true,
|
Storage: true,
|
||||||
Schema: &apiextensionsv1.CustomResourceValidation{
|
Schema: AllowAllSchema(),
|
||||||
OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{
|
|
||||||
XPreserveUnknownFields: pointer.BoolPtr(true),
|
|
||||||
Type: "object",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}},
|
}},
|
||||||
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||||
Plural: "noxus",
|
Plural: "noxus",
|
||||||
@ -173,13 +133,12 @@ func NewNoxuInstance(namespace, name string) *unstructured.Unstructured {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewMultipleVersionNoxuCRD returns a WishIHadChosenNoxu with multiple versions.
|
// NewMultipleVersionNoxuCRD returns a WishIHadChosenNoxu with multiple versions.
|
||||||
func NewMultipleVersionNoxuCRD(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition {
|
func NewMultipleVersionNoxuCRD(scope apiextensionsv1.ResourceScope) *apiextensionsv1.CustomResourceDefinition {
|
||||||
return &apiextensionsv1beta1.CustomResourceDefinition{
|
return &apiextensionsv1.CustomResourceDefinition{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"},
|
ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"},
|
||||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||||
Group: "mygroup.example.com",
|
Group: "mygroup.example.com",
|
||||||
Version: "v1beta1",
|
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
|
||||||
Plural: "noxus",
|
Plural: "noxus",
|
||||||
Singular: "nonenglishnoxu",
|
Singular: "nonenglishnoxu",
|
||||||
Kind: "WishIHadChosenNoxu",
|
Kind: "WishIHadChosenNoxu",
|
||||||
@ -188,38 +147,52 @@ func NewMultipleVersionNoxuCRD(scope apiextensionsv1beta1.ResourceScope) *apiext
|
|||||||
Categories: []string{"all"},
|
Categories: []string{"all"},
|
||||||
},
|
},
|
||||||
Scope: scope,
|
Scope: scope,
|
||||||
Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{
|
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||||
{
|
{
|
||||||
Name: "v1beta1",
|
Name: "v1beta1",
|
||||||
Served: true,
|
Served: true,
|
||||||
Storage: false,
|
Storage: false,
|
||||||
|
Subresources: &apiextensionsv1.CustomResourceSubresources{
|
||||||
|
Status: &apiextensionsv1.CustomResourceSubresourceStatus{},
|
||||||
|
},
|
||||||
|
Schema: AllowAllSchema(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "v1beta2",
|
Name: "v1beta2",
|
||||||
Served: true,
|
Served: true,
|
||||||
Storage: true,
|
Storage: true,
|
||||||
|
Subresources: &apiextensionsv1.CustomResourceSubresources{
|
||||||
|
Status: &apiextensionsv1.CustomResourceSubresourceStatus{},
|
||||||
|
},
|
||||||
|
Schema: AllowAllSchema(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "v0",
|
Name: "v0",
|
||||||
Served: false,
|
Served: false,
|
||||||
Storage: false,
|
Storage: false,
|
||||||
|
Subresources: &apiextensionsv1.CustomResourceSubresources{
|
||||||
|
Status: &apiextensionsv1.CustomResourceSubresourceStatus{},
|
||||||
|
},
|
||||||
|
Schema: AllowAllSchema(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Subresources: &apiextensionsv1beta1.CustomResourceSubresources{
|
|
||||||
Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNoxu2CustomResourceDefinition returns a WishIHadChosenNoxu2 CRD.
|
// NewNoxu2CustomResourceDefinition returns a WishIHadChosenNoxu2 CRD.
|
||||||
func NewNoxu2CustomResourceDefinition(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition {
|
func NewNoxu2CustomResourceDefinition(scope apiextensionsv1.ResourceScope) *apiextensionsv1.CustomResourceDefinition {
|
||||||
return &apiextensionsv1beta1.CustomResourceDefinition{
|
return &apiextensionsv1.CustomResourceDefinition{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "noxus2.mygroup.example.com"},
|
ObjectMeta: metav1.ObjectMeta{Name: "noxus2.mygroup.example.com"},
|
||||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||||
Group: "mygroup.example.com",
|
Group: "mygroup.example.com",
|
||||||
Version: "v1alpha1",
|
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{{
|
||||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
Name: "v1alpha1",
|
||||||
|
Served: true,
|
||||||
|
Storage: true,
|
||||||
|
Schema: AllowAllSchema(),
|
||||||
|
}},
|
||||||
|
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||||
Plural: "noxus2",
|
Plural: "noxus2",
|
||||||
Singular: "nonenglishnoxu2",
|
Singular: "nonenglishnoxu2",
|
||||||
Kind: "WishIHadChosenNoxu2",
|
Kind: "WishIHadChosenNoxu2",
|
||||||
@ -231,14 +204,21 @@ func NewNoxu2CustomResourceDefinition(scope apiextensionsv1beta1.ResourceScope)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCurletCustomResourceDefinition returns a Curlet CRD.
|
// NewCurletV1CustomResourceDefinition returns a Curlet CRD.
|
||||||
func NewCurletCustomResourceDefinition(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition {
|
func NewCurletV1CustomResourceDefinition(scope apiextensionsv1.ResourceScope) *apiextensionsv1.CustomResourceDefinition {
|
||||||
return &apiextensionsv1beta1.CustomResourceDefinition{
|
return &apiextensionsv1.CustomResourceDefinition{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "curlets.mygroup.example.com"},
|
ObjectMeta: metav1.ObjectMeta{Name: "curlets.mygroup.example.com"},
|
||||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||||
Group: "mygroup.example.com",
|
Group: "mygroup.example.com",
|
||||||
Version: "v1beta1",
|
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
{
|
||||||
|
Name: "v1beta1",
|
||||||
|
Served: true,
|
||||||
|
Storage: true,
|
||||||
|
Schema: AllowAllSchema(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||||
Plural: "curlets",
|
Plural: "curlets",
|
||||||
Singular: "curlet",
|
Singular: "curlet",
|
||||||
Kind: "Curlet",
|
Kind: "Curlet",
|
||||||
@ -506,23 +486,6 @@ func isWatchCachePrimed(crd *apiextensionsv1.CustomResourceDefinition, dynamicCl
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteCustomResourceDefinition deletes a CRD and waits until it disappears from discovery.
|
|
||||||
func DeleteCustomResourceDefinition(crd *apiextensionsv1beta1.CustomResourceDefinition, apiExtensionsClient clientset.Interface) error {
|
|
||||||
if err := apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Delete(context.TODO(), crd.Name, metav1.DeleteOptions{}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, version := range servedVersions(crd) {
|
|
||||||
err := wait.PollImmediate(500*time.Millisecond, 30*time.Second, func() (bool, error) {
|
|
||||||
exists, err := existsInDiscovery(crd, apiExtensionsClient, version)
|
|
||||||
return !exists, err
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteV1CustomResourceDefinition deletes a CRD and waits until it disappears from discovery.
|
// DeleteV1CustomResourceDefinition deletes a CRD and waits until it disappears from discovery.
|
||||||
func DeleteV1CustomResourceDefinition(crd *apiextensionsv1.CustomResourceDefinition, apiExtensionsClient clientset.Interface) error {
|
func DeleteV1CustomResourceDefinition(crd *apiextensionsv1.CustomResourceDefinition, apiExtensionsClient clientset.Interface) error {
|
||||||
if err := apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Delete(context.TODO(), crd.Name, metav1.DeleteOptions{}); err != nil {
|
if err := apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Delete(context.TODO(), crd.Name, metav1.DeleteOptions{}); err != nil {
|
||||||
@ -564,7 +527,7 @@ func DeleteV1CustomResourceDefinitions(deleteListOpts metav1.ListOptions, apiExt
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateNewVersionedScaleClient returns a scale client.
|
// CreateNewVersionedScaleClient returns a scale client.
|
||||||
func CreateNewVersionedScaleClient(crd *apiextensionsv1beta1.CustomResourceDefinition, config *rest.Config, version string) (scale.ScalesGetter, error) {
|
func CreateNewVersionedScaleClient(crd *apiextensionsv1.CustomResourceDefinition, config *rest.Config, version string) (scale.ScalesGetter, error) {
|
||||||
discoveryClient, err := discovery.NewDiscoveryClientForConfig(config)
|
discoveryClient, err := discovery.NewDiscoveryClientForConfig(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -20,9 +20,15 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"go.etcd.io/etcd/clientv3"
|
||||||
|
"go.etcd.io/etcd/pkg/transport"
|
||||||
|
"google.golang.org/grpc"
|
||||||
"k8s.io/apiextensions-apiserver/pkg/cmd/server/options"
|
"k8s.io/apiextensions-apiserver/pkg/cmd/server/options"
|
||||||
|
serveroptions "k8s.io/apiextensions-apiserver/pkg/cmd/server/options"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
|
||||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
servertesting "k8s.io/apiextensions-apiserver/pkg/cmd/server/testing"
|
servertesting "k8s.io/apiextensions-apiserver/pkg/cmd/server/testing"
|
||||||
@ -103,6 +109,55 @@ func StartDefaultServerWithClients(t servertesting.Logger, extraFlags ...string)
|
|||||||
return tearDown, apiExtensionsClient, dynamicClient, nil
|
return tearDown, apiExtensionsClient, dynamicClient, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StartDefaultServerWithClientsAndEtcd starts a test server and returns clients for it.
|
||||||
|
func StartDefaultServerWithClientsAndEtcd(t servertesting.Logger, extraFlags ...string) (func(), clientset.Interface, dynamic.Interface, *clientv3.Client, string, error) {
|
||||||
|
tearDown, config, options, err := StartDefaultServer(t, extraFlags...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
apiExtensionsClient, err := clientset.NewForConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
tearDown()
|
||||||
|
return nil, nil, nil, nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
dynamicClient, err := dynamic.NewForConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
tearDown()
|
||||||
|
return nil, nil, nil, nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
RESTOptionsGetter := serveroptions.NewCRDRESTOptionsGetter(*options.RecommendedOptions.Etcd)
|
||||||
|
restOptions, err := RESTOptionsGetter.GetRESTOptions(schema.GroupResource{Group: "hopefully-ignored-group", Resource: "hopefully-ignored-resources"})
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, nil, "", err
|
||||||
|
}
|
||||||
|
tlsInfo := transport.TLSInfo{
|
||||||
|
CertFile: restOptions.StorageConfig.Transport.CertFile,
|
||||||
|
KeyFile: restOptions.StorageConfig.Transport.KeyFile,
|
||||||
|
TrustedCAFile: restOptions.StorageConfig.Transport.TrustedCAFile,
|
||||||
|
}
|
||||||
|
tlsConfig, err := tlsInfo.ClientConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, nil, "", err
|
||||||
|
}
|
||||||
|
etcdConfig := clientv3.Config{
|
||||||
|
Endpoints: restOptions.StorageConfig.Transport.ServerList,
|
||||||
|
DialTimeout: 20 * time.Second,
|
||||||
|
DialOptions: []grpc.DialOption{
|
||||||
|
grpc.WithBlock(), // block until the underlying connection is up
|
||||||
|
},
|
||||||
|
TLS: tlsConfig,
|
||||||
|
}
|
||||||
|
etcdclient, err := clientv3.New(etcdConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tearDown, apiExtensionsClient, dynamicClient, etcdclient, restOptions.StorageConfig.Prefix, nil
|
||||||
|
}
|
||||||
|
|
||||||
// IntegrationEtcdServers returns etcd server URLs.
|
// IntegrationEtcdServers returns etcd server URLs.
|
||||||
func IntegrationEtcdServers() []string {
|
func IntegrationEtcdServers() []string {
|
||||||
if etcdURL, ok := os.LookupEnv("KUBE_INTEGRATION_ETCD_URL"); ok {
|
if etcdURL, ok := os.LookupEnv("KUBE_INTEGRATION_ETCD_URL"); ok {
|
||||||
|
@ -22,7 +22,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
apiextensionsv1beta1 "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/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/api/meta"
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
@ -34,11 +33,11 @@ import (
|
|||||||
|
|
||||||
var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc()
|
var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc()
|
||||||
|
|
||||||
func instantiateCustomResource(t *testing.T, instanceToCreate *unstructured.Unstructured, client dynamic.ResourceInterface, definition *apiextensionsv1beta1.CustomResourceDefinition) (*unstructured.Unstructured, error) {
|
func instantiateCustomResource(t *testing.T, instanceToCreate *unstructured.Unstructured, client dynamic.ResourceInterface, definition *apiextensionsv1.CustomResourceDefinition) (*unstructured.Unstructured, error) {
|
||||||
return instantiateVersionedCustomResource(t, instanceToCreate, client, definition, definition.Spec.Versions[0].Name)
|
return instantiateVersionedCustomResource(t, instanceToCreate, client, definition, definition.Spec.Versions[0].Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func instantiateVersionedCustomResource(t *testing.T, instanceToCreate *unstructured.Unstructured, client dynamic.ResourceInterface, definition *apiextensionsv1beta1.CustomResourceDefinition, version string) (*unstructured.Unstructured, error) {
|
func instantiateVersionedCustomResource(t *testing.T, instanceToCreate *unstructured.Unstructured, client dynamic.ResourceInterface, definition *apiextensionsv1.CustomResourceDefinition, version string) (*unstructured.Unstructured, error) {
|
||||||
createdInstance, err := client.Create(context.TODO(), instanceToCreate, metav1.CreateOptions{})
|
createdInstance, err := client.Create(context.TODO(), instanceToCreate, metav1.CreateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Logf("%#v", createdInstance)
|
t.Logf("%#v", createdInstance)
|
||||||
@ -65,28 +64,28 @@ func instantiateVersionedCustomResource(t *testing.T, instanceToCreate *unstruct
|
|||||||
return createdInstance, nil
|
return createdInstance, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newNamespacedCustomResourceVersionedClient(ns string, client dynamic.Interface, crd *apiextensionsv1beta1.CustomResourceDefinition, version string) dynamic.ResourceInterface {
|
func newNamespacedCustomResourceVersionedClient(ns string, client dynamic.Interface, crd *apiextensionsv1.CustomResourceDefinition, version string) dynamic.ResourceInterface {
|
||||||
gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: version, Resource: crd.Spec.Names.Plural}
|
gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: version, Resource: crd.Spec.Names.Plural}
|
||||||
|
|
||||||
if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped {
|
if crd.Spec.Scope != apiextensionsv1.ClusterScoped {
|
||||||
return client.Resource(gvr).Namespace(ns)
|
return client.Resource(gvr).Namespace(ns)
|
||||||
}
|
}
|
||||||
return client.Resource(gvr)
|
return client.Resource(gvr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newNamespacedCustomResourceClient(ns string, client dynamic.Interface, crd *apiextensionsv1beta1.CustomResourceDefinition) dynamic.ResourceInterface {
|
func newNamespacedCustomResourceClient(ns string, client dynamic.Interface, crd *apiextensionsv1.CustomResourceDefinition) dynamic.ResourceInterface {
|
||||||
return newNamespacedCustomResourceVersionedClient(ns, client, crd, crd.Spec.Versions[0].Name)
|
return newNamespacedCustomResourceVersionedClient(ns, client, crd, crd.Spec.Versions[0].Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateCustomResourceDefinitionWithRetry updates a CRD, retrying up to 5 times on version conflict errors.
|
// UpdateCustomResourceDefinitionWithRetry updates a CRD, retrying up to 5 times on version conflict errors.
|
||||||
func UpdateCustomResourceDefinitionWithRetry(client clientset.Interface, name string, update func(*apiextensionsv1beta1.CustomResourceDefinition)) (*apiextensionsv1beta1.CustomResourceDefinition, error) {
|
func UpdateCustomResourceDefinitionWithRetry(client clientset.Interface, name string, update func(*apiextensionsv1.CustomResourceDefinition)) (*apiextensionsv1.CustomResourceDefinition, error) {
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
crd, err := client.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{})
|
crd, err := client.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get CustomResourceDefinition %q: %v", name, err)
|
return nil, fmt.Errorf("failed to get CustomResourceDefinition %q: %v", name, err)
|
||||||
}
|
}
|
||||||
update(crd)
|
update(crd)
|
||||||
crd, err = client.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{})
|
crd, err = client.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return crd, nil
|
return crd, nil
|
||||||
}
|
}
|
||||||
@ -117,13 +116,7 @@ func UpdateV1CustomResourceDefinitionWithRetry(client clientset.Interface, name
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getSchemaForVersion returns the validation schema for given version in given CRD.
|
// getSchemaForVersion returns the validation schema for given version in given CRD.
|
||||||
func getSchemaForVersion(crd *apiextensionsv1beta1.CustomResourceDefinition, version string) (*apiextensionsv1beta1.CustomResourceValidation, error) {
|
func getSchemaForVersion(crd *apiextensionsv1.CustomResourceDefinition, version string) (*apiextensionsv1.CustomResourceValidation, error) {
|
||||||
if !hasPerVersionSchema(crd.Spec.Versions) {
|
|
||||||
return crd.Spec.Validation, nil
|
|
||||||
}
|
|
||||||
if crd.Spec.Validation != nil {
|
|
||||||
return nil, fmt.Errorf("malformed CustomResourceDefinition %s version %s: top-level and per-version schemas must be mutual exclusive", crd.Name, version)
|
|
||||||
}
|
|
||||||
for _, v := range crd.Spec.Versions {
|
for _, v := range crd.Spec.Versions {
|
||||||
if version == v.Name {
|
if version == v.Name {
|
||||||
return v.Schema, nil
|
return v.Schema, nil
|
||||||
@ -133,13 +126,7 @@ func getSchemaForVersion(crd *apiextensionsv1beta1.CustomResourceDefinition, ver
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getSubresourcesForVersion returns the subresources for given version in given CRD.
|
// getSubresourcesForVersion returns the subresources for given version in given CRD.
|
||||||
func getSubresourcesForVersion(crd *apiextensionsv1beta1.CustomResourceDefinition, version string) (*apiextensionsv1beta1.CustomResourceSubresources, error) {
|
func getSubresourcesForVersion(crd *apiextensionsv1.CustomResourceDefinition, version string) (*apiextensionsv1.CustomResourceSubresources, error) {
|
||||||
if !hasPerVersionSubresources(crd.Spec.Versions) {
|
|
||||||
return crd.Spec.Subresources, nil
|
|
||||||
}
|
|
||||||
if crd.Spec.Subresources != nil {
|
|
||||||
return nil, fmt.Errorf("malformed CustomResourceDefinition %s version %s: top-level and per-version subresources must be mutual exclusive", crd.Name, version)
|
|
||||||
}
|
|
||||||
for _, v := range crd.Spec.Versions {
|
for _, v := range crd.Spec.Versions {
|
||||||
if version == v.Name {
|
if version == v.Name {
|
||||||
return v.Subresources, nil
|
return v.Subresources, nil
|
||||||
@ -152,13 +139,7 @@ func getSubresourcesForVersion(crd *apiextensionsv1beta1.CustomResourceDefinitio
|
|||||||
// NOTE: the newly logically-defaulted columns is not pointing to the original CRD object.
|
// NOTE: the newly logically-defaulted columns is not pointing to the original CRD object.
|
||||||
// One cannot mutate the original CRD columns using the logically-defaulted columns. Please iterate through
|
// One cannot mutate the original CRD columns using the logically-defaulted columns. Please iterate through
|
||||||
// the original CRD object instead.
|
// the original CRD object instead.
|
||||||
func getColumnsForVersion(crd *apiextensionsv1beta1.CustomResourceDefinition, version string) ([]apiextensionsv1beta1.CustomResourceColumnDefinition, error) {
|
func getColumnsForVersion(crd *apiextensionsv1.CustomResourceDefinition, version string) ([]apiextensionsv1.CustomResourceColumnDefinition, error) {
|
||||||
if !hasPerVersionColumns(crd.Spec.Versions) {
|
|
||||||
return serveDefaultColumnsIfEmpty(crd.Spec.AdditionalPrinterColumns), nil
|
|
||||||
}
|
|
||||||
if len(crd.Spec.AdditionalPrinterColumns) > 0 {
|
|
||||||
return nil, fmt.Errorf("malformed CustomResourceDefinition %s version %s: top-level and per-version additionalPrinterColumns must be mutual exclusive", crd.Name, version)
|
|
||||||
}
|
|
||||||
for _, v := range crd.Spec.Versions {
|
for _, v := range crd.Spec.Versions {
|
||||||
if version == v.Name {
|
if version == v.Name {
|
||||||
return serveDefaultColumnsIfEmpty(v.AdditionalPrinterColumns), nil
|
return serveDefaultColumnsIfEmpty(v.AdditionalPrinterColumns), nil
|
||||||
@ -171,41 +152,11 @@ func getColumnsForVersion(crd *apiextensionsv1beta1.CustomResourceDefinition, ve
|
|||||||
// NOTE: in this way, the newly logically-defaulted columns is not pointing to the original CRD object.
|
// NOTE: in this way, the newly logically-defaulted columns is not pointing to the original CRD object.
|
||||||
// One cannot mutate the original CRD columns using the logically-defaulted columns. Please iterate through
|
// One cannot mutate the original CRD columns using the logically-defaulted columns. Please iterate through
|
||||||
// the original CRD object instead.
|
// the original CRD object instead.
|
||||||
func serveDefaultColumnsIfEmpty(columns []apiextensionsv1beta1.CustomResourceColumnDefinition) []apiextensionsv1beta1.CustomResourceColumnDefinition {
|
func serveDefaultColumnsIfEmpty(columns []apiextensionsv1.CustomResourceColumnDefinition) []apiextensionsv1.CustomResourceColumnDefinition {
|
||||||
if len(columns) > 0 {
|
if len(columns) > 0 {
|
||||||
return columns
|
return columns
|
||||||
}
|
}
|
||||||
return []apiextensionsv1beta1.CustomResourceColumnDefinition{
|
return []apiextensionsv1.CustomResourceColumnDefinition{
|
||||||
{Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"},
|
{Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// hasPerVersionSchema returns true if a CRD uses per-version schema.
|
|
||||||
func hasPerVersionSchema(versions []apiextensionsv1beta1.CustomResourceDefinitionVersion) bool {
|
|
||||||
for _, v := range versions {
|
|
||||||
if v.Schema != nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// hasPerVersionSubresources returns true if a CRD uses per-version subresources.
|
|
||||||
func hasPerVersionSubresources(versions []apiextensionsv1beta1.CustomResourceDefinitionVersion) bool {
|
|
||||||
for _, v := range versions {
|
|
||||||
if v.Subresources != nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// hasPerVersionColumns returns true if a CRD uses per-version columns.
|
|
||||||
func hasPerVersionColumns(versions []apiextensionsv1beta1.CustomResourceDefinitionVersion) bool {
|
|
||||||
for _, v := range versions {
|
|
||||||
if len(v.AdditionalPrinterColumns) > 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
@ -22,13 +22,12 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"k8s.io/client-go/dynamic"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
|
|
||||||
apiextensionsv1beta1 "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/test/integration/fixtures"
|
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLimits(t *testing.T) {
|
func TestLimits(t *testing.T) {
|
||||||
@ -47,14 +46,14 @@ func TestLimits(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
kind := noxuDefinition.Spec.Names.Kind
|
kind := noxuDefinition.Spec.Names.Kind
|
||||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Version
|
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name
|
||||||
|
|
||||||
rest := apiExtensionClient.Discovery().RESTClient()
|
rest := apiExtensionClient.Discovery().RESTClient()
|
||||||
|
|
||||||
@ -70,7 +69,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind))
|
|||||||
_, err := rest.Post().
|
_, err := rest.Post().
|
||||||
SetHeader("Accept", "application/yaml").
|
SetHeader("Accept", "application/yaml").
|
||||||
SetHeader("Content-Type", "application/yaml").
|
SetHeader("Content-Type", "application/yaml").
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Body(yamlBody).
|
Body(yamlBody).
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
if !apierrors.IsRequestEntityTooLargeError(err) {
|
if !apierrors.IsRequestEntityTooLargeError(err) {
|
||||||
@ -93,7 +92,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind))
|
|||||||
_, err := rest.Post().
|
_, err := rest.Post().
|
||||||
SetHeader("Accept", "application/yaml").
|
SetHeader("Accept", "application/yaml").
|
||||||
SetHeader("Content-Type", "application/yaml").
|
SetHeader("Content-Type", "application/yaml").
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Body(yamlBody).
|
Body(yamlBody).
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
if !apierrors.IsBadRequest(err) {
|
if !apierrors.IsBadRequest(err) {
|
||||||
@ -116,7 +115,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind))
|
|||||||
_, err := rest.Post().
|
_, err := rest.Post().
|
||||||
SetHeader("Accept", "application/yaml").
|
SetHeader("Accept", "application/yaml").
|
||||||
SetHeader("Content-Type", "application/yaml").
|
SetHeader("Content-Type", "application/yaml").
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Body(yamlBody).
|
Body(yamlBody).
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
if !apierrors.IsBadRequest(err) {
|
if !apierrors.IsBadRequest(err) {
|
||||||
@ -137,7 +136,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind))
|
|||||||
_, err := rest.Post().
|
_, err := rest.Post().
|
||||||
SetHeader("Accept", "application/json").
|
SetHeader("Accept", "application/json").
|
||||||
SetHeader("Content-Type", "application/json").
|
SetHeader("Content-Type", "application/json").
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Body(jsonBody).
|
Body(jsonBody).
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
if !apierrors.IsRequestEntityTooLargeError(err) {
|
if !apierrors.IsRequestEntityTooLargeError(err) {
|
||||||
@ -161,7 +160,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind))
|
|||||||
_, err := rest.Post().
|
_, err := rest.Post().
|
||||||
SetHeader("Accept", "application/json").
|
SetHeader("Accept", "application/json").
|
||||||
SetHeader("Content-Type", "application/json").
|
SetHeader("Content-Type", "application/json").
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Body(jsonBody).
|
Body(jsonBody).
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
if !apierrors.IsBadRequest(err) {
|
if !apierrors.IsBadRequest(err) {
|
||||||
@ -185,7 +184,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind))
|
|||||||
_, err := rest.Post().
|
_, err := rest.Post().
|
||||||
SetHeader("Accept", "application/json").
|
SetHeader("Accept", "application/json").
|
||||||
SetHeader("Content-Type", "application/json").
|
SetHeader("Content-Type", "application/json").
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Body(jsonBody).
|
Body(jsonBody).
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
if !apierrors.IsBadRequest(err) {
|
if !apierrors.IsBadRequest(err) {
|
||||||
@ -196,7 +195,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind))
|
|||||||
// Create instance to allow patching
|
// Create instance to allow patching
|
||||||
{
|
{
|
||||||
jsonBody := []byte(fmt.Sprintf(`{"apiVersion": %q, "kind": %q, "metadata": {"name": "test"}}`, apiVersion, kind))
|
jsonBody := []byte(fmt.Sprintf(`{"apiVersion": %q, "kind": %q, "metadata": {"name": "test"}}`, apiVersion, kind))
|
||||||
_, err := rest.Post().AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).Body(jsonBody).DoRaw(context.TODO())
|
_, err := rest.Post().AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).Body(jsonBody).DoRaw(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error creating object: %v", err)
|
t.Fatalf("error creating object: %v", err)
|
||||||
}
|
}
|
||||||
@ -207,7 +206,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind))
|
|||||||
t.Skip("skipping expensive test")
|
t.Skip("skipping expensive test")
|
||||||
}
|
}
|
||||||
patchBody := []byte(`[{"op":"add","path":"/foo","value":` + strings.Repeat("[", 3*1024*1024/2-100) + strings.Repeat("]", 3*1024*1024/2-100) + `}]`)
|
patchBody := []byte(`[{"op":"add","path":"/foo","value":` + strings.Repeat("[", 3*1024*1024/2-100) + strings.Repeat("]", 3*1024*1024/2-100) + `}]`)
|
||||||
err = rest.Patch(types.JSONPatchType).AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "test").
|
err = rest.Patch(types.JSONPatchType).AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "test").
|
||||||
Body(patchBody).Do(context.TODO()).Error()
|
Body(patchBody).Do(context.TODO()).Error()
|
||||||
if !apierrors.IsBadRequest(err) {
|
if !apierrors.IsBadRequest(err) {
|
||||||
t.Errorf("expected success or bad request err, got %v", err)
|
t.Errorf("expected success or bad request err, got %v", err)
|
||||||
@ -218,7 +217,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind))
|
|||||||
t.Skip("skipping expensive test")
|
t.Skip("skipping expensive test")
|
||||||
}
|
}
|
||||||
patchBody := []byte(`{"value":` + strings.Repeat("[", 3*1024*1024/2-100) + strings.Repeat("]", 3*1024*1024/2-100) + `}`)
|
patchBody := []byte(`{"value":` + strings.Repeat("[", 3*1024*1024/2-100) + strings.Repeat("]", 3*1024*1024/2-100) + `}`)
|
||||||
err = rest.Patch(types.MergePatchType).AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "test").
|
err = rest.Patch(types.MergePatchType).AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "test").
|
||||||
Body(patchBody).Do(context.TODO()).Error()
|
Body(patchBody).Do(context.TODO()).Error()
|
||||||
if !apierrors.IsBadRequest(err) {
|
if !apierrors.IsBadRequest(err) {
|
||||||
t.Errorf("expected success or bad request err, got %v", err)
|
t.Errorf("expected success or bad request err, got %v", err)
|
||||||
@ -229,7 +228,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind))
|
|||||||
t.Skip("skipping expensive test")
|
t.Skip("skipping expensive test")
|
||||||
}
|
}
|
||||||
patchBody := []byte(`{"value":` + strings.Repeat("[", 3*1024*1024/2-100) + strings.Repeat("]", 3*1024*1024/2-100) + `}`)
|
patchBody := []byte(`{"value":` + strings.Repeat("[", 3*1024*1024/2-100) + strings.Repeat("]", 3*1024*1024/2-100) + `}`)
|
||||||
err = rest.Patch(types.ApplyPatchType).Param("fieldManager", "test").AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "test").
|
err = rest.Patch(types.ApplyPatchType).Param("fieldManager", "test").AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "test").
|
||||||
Body(patchBody).Do(context.TODO()).Error()
|
Body(patchBody).Do(context.TODO()).Error()
|
||||||
if !apierrors.IsBadRequest(err) {
|
if !apierrors.IsBadRequest(err) {
|
||||||
t.Errorf("expected bad request err, got %#v", err)
|
t.Errorf("expected bad request err, got %#v", err)
|
||||||
|
@ -22,37 +22,36 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
|
||||||
"k8s.io/client-go/util/retry"
|
|
||||||
"sigs.k8s.io/yaml"
|
|
||||||
|
|
||||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
|
||||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
|
"k8s.io/client-go/util/retry"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
var listTypeResourceFixture = &apiextensionsv1beta1.CustomResourceDefinition{
|
var listTypeResourceFixture = &apiextensionsv1.CustomResourceDefinition{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "foos.tests.example.com"},
|
ObjectMeta: metav1.ObjectMeta{Name: "foos.tests.example.com"},
|
||||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||||
Group: "tests.example.com",
|
Group: "tests.example.com",
|
||||||
Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{
|
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||||
{
|
{
|
||||||
Name: "v1beta1",
|
Name: "v1beta1",
|
||||||
Storage: true,
|
Storage: true,
|
||||||
Served: true,
|
Served: true,
|
||||||
|
Schema: fixtures.AllowAllSchema(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||||
Plural: "foos",
|
Plural: "foos",
|
||||||
Singular: "foo",
|
Singular: "foo",
|
||||||
Kind: "Foo",
|
Kind: "Foo",
|
||||||
ListKind: "FooList",
|
ListKind: "FooList",
|
||||||
},
|
},
|
||||||
Scope: apiextensionsv1beta1.ClusterScoped,
|
Scope: apiextensionsv1.ClusterScoped,
|
||||||
Validation: &apiextensionsv1beta1.CustomResourceValidation{},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,11 +127,11 @@ func TestListTypes(t *testing.T) {
|
|||||||
defer tearDownFn()
|
defer tearDownFn()
|
||||||
|
|
||||||
crd := listTypeResourceFixture.DeepCopy()
|
crd := listTypeResourceFixture.DeepCopy()
|
||||||
if err := yaml.Unmarshal([]byte(listTypeResourceSchema), &crd.Spec.Validation.OpenAPIV3Schema); err != nil {
|
if err := yaml.Unmarshal([]byte(listTypeResourceSchema), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -195,14 +194,14 @@ func TestListTypes(t *testing.T) {
|
|||||||
|
|
||||||
t.Logf("Remove \"b\" from the keys in the schema which renders the valid instance invalid")
|
t.Logf("Remove \"b\" from the keys in the schema which renders the valid instance invalid")
|
||||||
err = retry.RetryOnConflict(retry.DefaultBackoff, func() error {
|
err = retry.RetryOnConflict(retry.DefaultBackoff, func() error {
|
||||||
crd, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{})
|
crd, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s := crd.Spec.Validation.OpenAPIV3Schema.Properties["correct-map"]
|
s := crd.Spec.Versions[0].Schema.OpenAPIV3Schema.Properties["correct-map"]
|
||||||
s.XListMapKeys = []string{"a"}
|
s.XListMapKeys = []string{"a"}
|
||||||
crd.Spec.Validation.OpenAPIV3Schema.Properties["correct-map"] = s
|
crd.Spec.Versions[0].Schema.OpenAPIV3Schema.Properties["correct-map"] = s
|
||||||
_, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{})
|
_, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{})
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -30,7 +30,6 @@ import (
|
|||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
|
|
||||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
|
||||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
serveroptions "k8s.io/apiextensions-apiserver/pkg/cmd/server/options"
|
serveroptions "k8s.io/apiextensions-apiserver/pkg/cmd/server/options"
|
||||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
@ -52,8 +51,8 @@ func TestPostInvalidObjectMeta(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -114,11 +113,11 @@ func TestInvalidObjectMetaInStorage(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||||
noxuDefinition.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{
|
noxuDefinition.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{
|
||||||
OpenAPIV3Schema: &apiextensionsv1beta1.JSONSchemaProps{
|
OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
|
Properties: map[string]apiextensionsv1.JSONSchemaProps{
|
||||||
"embedded": {
|
"embedded": {
|
||||||
Type: "object",
|
Type: "object",
|
||||||
XEmbeddedResource: true,
|
XEmbeddedResource: true,
|
||||||
@ -127,7 +126,7 @@ func TestInvalidObjectMetaInStorage(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
|
|
||||||
"go.etcd.io/etcd/clientv3"
|
"go.etcd.io/etcd/clientv3"
|
||||||
"go.etcd.io/etcd/pkg/transport"
|
"go.etcd.io/etcd/pkg/transport"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
@ -39,29 +41,37 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/json"
|
"k8s.io/apimachinery/pkg/util/json"
|
||||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||||
"k8s.io/client-go/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
"k8s.io/utils/pointer"
|
|
||||||
|
|
||||||
apiextensionsv1beta1 "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/test/integration/fixtures"
|
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
)
|
)
|
||||||
|
|
||||||
var pruningFixture = &apiextensionsv1beta1.CustomResourceDefinition{
|
var pruningFixture = &apiextensionsv1.CustomResourceDefinition{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "foos.tests.example.com"},
|
ObjectMeta: metav1.ObjectMeta{Name: "foos.tests.example.com"},
|
||||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||||
Group: "tests.example.com",
|
Group: "tests.example.com",
|
||||||
Version: "v1beta1",
|
Scope: apiextensionsv1.ClusterScoped,
|
||||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||||
|
{
|
||||||
|
Name: "v1beta1",
|
||||||
|
Served: true,
|
||||||
|
Storage: true,
|
||||||
|
Subresources: &apiextensionsv1.CustomResourceSubresources{
|
||||||
|
Status: &apiextensionsv1.CustomResourceSubresourceStatus{},
|
||||||
|
},
|
||||||
|
Schema: &apiextensionsv1.CustomResourceValidation{
|
||||||
|
OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{
|
||||||
|
Type: "object",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||||
Plural: "foos",
|
Plural: "foos",
|
||||||
Singular: "foo",
|
Singular: "foo",
|
||||||
Kind: "Foo",
|
Kind: "Foo",
|
||||||
ListKind: "FooList",
|
ListKind: "FooList",
|
||||||
},
|
},
|
||||||
Scope: apiextensionsv1beta1.ClusterScoped,
|
|
||||||
PreserveUnknownFields: pointer.BoolPtr(false),
|
|
||||||
Subresources: &apiextensionsv1beta1.CustomResourceSubresources{
|
|
||||||
Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,18 +199,18 @@ func TestPruningCreate(t *testing.T) {
|
|||||||
defer tearDownFn()
|
defer tearDownFn()
|
||||||
|
|
||||||
crd := pruningFixture.DeepCopy()
|
crd := pruningFixture.DeepCopy()
|
||||||
crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{}
|
crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{}
|
||||||
if err := yaml.Unmarshal([]byte(fooSchema), &crd.Spec.Validation.OpenAPIV3Schema); err != nil {
|
if err := yaml.Unmarshal([]byte(fooSchema), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Logf("Creating CR and expect 'unspecified' fields to be pruned")
|
t.Logf("Creating CR and expect 'unspecified' fields to be pruned")
|
||||||
fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Version, crd.Spec.Names.Plural})
|
fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Versions[0].Name, crd.Spec.Names.Plural})
|
||||||
foo := &unstructured.Unstructured{}
|
foo := &unstructured.Unstructured{}
|
||||||
if err := yaml.Unmarshal([]byte(pruningFooInstance), &foo.Object); err != nil {
|
if err := yaml.Unmarshal([]byte(pruningFooInstance), &foo.Object); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -241,18 +251,18 @@ func TestPruningStatus(t *testing.T) {
|
|||||||
defer tearDownFn()
|
defer tearDownFn()
|
||||||
|
|
||||||
crd := pruningFixture.DeepCopy()
|
crd := pruningFixture.DeepCopy()
|
||||||
crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{}
|
crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{}
|
||||||
if err := yaml.Unmarshal([]byte(fooStatusSchema), &crd.Spec.Validation.OpenAPIV3Schema); err != nil {
|
if err := yaml.Unmarshal([]byte(fooStatusSchema), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Logf("Creating CR and expect 'unspecified' fields to be pruned")
|
t.Logf("Creating CR and expect 'unspecified' fields to be pruned")
|
||||||
fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Version, crd.Spec.Names.Plural})
|
fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Versions[0].Name, crd.Spec.Names.Plural})
|
||||||
foo := &unstructured.Unstructured{}
|
foo := &unstructured.Unstructured{}
|
||||||
if err := yaml.Unmarshal([]byte(pruningFooInstance), &foo.Object); err != nil {
|
if err := yaml.Unmarshal([]byte(pruningFooInstance), &foo.Object); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -310,12 +320,12 @@ func TestPruningFromStorage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
crd := pruningFixture.DeepCopy()
|
crd := pruningFixture.DeepCopy()
|
||||||
crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{}
|
crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{}
|
||||||
if err := yaml.Unmarshal([]byte(fooSchema), &crd.Spec.Validation.OpenAPIV3Schema); err != nil {
|
if err := yaml.Unmarshal([]byte(fooSchema), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -368,7 +378,7 @@ func TestPruningFromStorage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Logf("Checking that CustomResource is pruned from unknown fields")
|
t.Logf("Checking that CustomResource is pruned from unknown fields")
|
||||||
fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Version, crd.Spec.Names.Plural})
|
fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Versions[0].Name, crd.Spec.Names.Plural})
|
||||||
foo, err := fooClient.Get(context.TODO(), "foo", metav1.GetOptions{})
|
foo, err := fooClient.Get(context.TODO(), "foo", metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
@ -400,16 +410,16 @@ func TestPruningPatch(t *testing.T) {
|
|||||||
defer tearDownFn()
|
defer tearDownFn()
|
||||||
|
|
||||||
crd := pruningFixture.DeepCopy()
|
crd := pruningFixture.DeepCopy()
|
||||||
crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{}
|
crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{}
|
||||||
if err := yaml.Unmarshal([]byte(fooSchema), &crd.Spec.Validation.OpenAPIV3Schema); err != nil {
|
if err := yaml.Unmarshal([]byte(fooSchema), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Version, crd.Spec.Names.Plural})
|
fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Versions[0].Name, crd.Spec.Names.Plural})
|
||||||
foo := &unstructured.Unstructured{}
|
foo := &unstructured.Unstructured{}
|
||||||
if err := yaml.Unmarshal([]byte(pruningFooInstance), &foo.Object); err != nil {
|
if err := yaml.Unmarshal([]byte(pruningFooInstance), &foo.Object); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -451,18 +461,18 @@ func TestPruningCreatePreservingUnknownFields(t *testing.T) {
|
|||||||
defer tearDownFn()
|
defer tearDownFn()
|
||||||
|
|
||||||
crd := pruningFixture.DeepCopy()
|
crd := pruningFixture.DeepCopy()
|
||||||
crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{}
|
crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{}
|
||||||
if err := yaml.Unmarshal([]byte(fooSchemaPreservingUnknownFields), &crd.Spec.Validation.OpenAPIV3Schema); err != nil {
|
if err := yaml.Unmarshal([]byte(fooSchemaPreservingUnknownFields), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Logf("Creating CR and expect 'unspecified' field to be pruned")
|
t.Logf("Creating CR and expect 'unspecified' field to be pruned")
|
||||||
fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Version, crd.Spec.Names.Plural})
|
fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Versions[0].Name, crd.Spec.Names.Plural})
|
||||||
foo := &unstructured.Unstructured{}
|
foo := &unstructured.Unstructured{}
|
||||||
if err := yaml.Unmarshal([]byte(pruningFooInstance), &foo.Object); err != nil {
|
if err := yaml.Unmarshal([]byte(pruningFooInstance), &foo.Object); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -536,18 +546,18 @@ func TestPruningEmbeddedResources(t *testing.T) {
|
|||||||
defer tearDownFn()
|
defer tearDownFn()
|
||||||
|
|
||||||
crd := pruningFixture.DeepCopy()
|
crd := pruningFixture.DeepCopy()
|
||||||
crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{}
|
crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{}
|
||||||
if err := yaml.Unmarshal([]byte(fooSchemaEmbeddedResource), &crd.Spec.Validation.OpenAPIV3Schema); err != nil {
|
if err := yaml.Unmarshal([]byte(fooSchemaEmbeddedResource), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Logf("Creating CR and expect 'unspecified' field to be pruned")
|
t.Logf("Creating CR and expect 'unspecified' field to be pruned")
|
||||||
fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Version, crd.Spec.Names.Plural})
|
fooClient := dynamicClient.Resource(schema.GroupVersionResource{crd.Spec.Group, crd.Spec.Versions[0].Name, crd.Spec.Names.Plural})
|
||||||
foo := &unstructured.Unstructured{}
|
foo := &unstructured.Unstructured{}
|
||||||
if err := yaml.Unmarshal([]byte(fooSchemaEmbeddedResourceInstance), &foo.Object); err != nil {
|
if err := yaml.Unmarshal([]byte(fooSchemaEmbeddedResourceInstance), &foo.Object); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -28,7 +28,7 @@ import (
|
|||||||
|
|
||||||
"go.etcd.io/etcd/clientv3"
|
"go.etcd.io/etcd/clientv3"
|
||||||
|
|
||||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
@ -47,8 +47,8 @@ func TestMultipleResourceInstances(t *testing.T) {
|
|||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
ns := "not-the-default"
|
ns := "not-the-default"
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -172,8 +172,8 @@ func TestMultipleRegistration(t *testing.T) {
|
|||||||
|
|
||||||
ns := "not-the-default"
|
ns := "not-the-default"
|
||||||
sameInstanceName := "foo"
|
sameInstanceName := "foo"
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -191,8 +191,8 @@ func TestMultipleRegistration(t *testing.T) {
|
|||||||
t.Errorf("expected %v, got %v", e, a)
|
t.Errorf("expected %v, got %v", e, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
curletDefinition := fixtures.NewCurletCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
curletDefinition := fixtures.NewCurletV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||||
curletDefinition, err = fixtures.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient)
|
curletDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -225,11 +225,11 @@ func TestDeRegistrationAndReRegistration(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||||
ns := "not-the-default"
|
ns := "not-the-default"
|
||||||
sameInstanceName := "foo"
|
sameInstanceName := "foo"
|
||||||
func() {
|
func() {
|
||||||
noxuDefinition, err := fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err := fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -237,10 +237,10 @@ func TestDeRegistrationAndReRegistration(t *testing.T) {
|
|||||||
if _, err := instantiateCustomResource(t, fixtures.NewNoxuInstance(ns, sameInstanceName), noxuNamespacedResourceClient, noxuDefinition); err != nil {
|
if _, err := instantiateCustomResource(t, fixtures.NewNoxuInstance(ns, sameInstanceName), noxuNamespacedResourceClient, noxuDefinition); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if _, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{}); err == nil || !errors.IsNotFound(err) {
|
if _, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{}); err == nil || !errors.IsNotFound(err) {
|
||||||
t.Fatalf("expected a NotFound error, got:%v", err)
|
t.Fatalf("expected a NotFound error, got:%v", err)
|
||||||
}
|
}
|
||||||
if _, err = noxuNamespacedResourceClient.List(context.TODO(), metav1.ListOptions{}); err == nil || !errors.IsNotFound(err) {
|
if _, err = noxuNamespacedResourceClient.List(context.TODO(), metav1.ListOptions{}); err == nil || !errors.IsNotFound(err) {
|
||||||
@ -252,10 +252,10 @@ func TestDeRegistrationAndReRegistration(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
func() {
|
func() {
|
||||||
if _, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{}); err == nil || !errors.IsNotFound(err) {
|
if _, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{}); err == nil || !errors.IsNotFound(err) {
|
||||||
t.Fatalf("expected a NotFound error, got:%v", err)
|
t.Fatalf("expected a NotFound error, got:%v", err)
|
||||||
}
|
}
|
||||||
noxuDefinition, err := fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err := fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -327,8 +327,8 @@ func TestEtcdStorage(t *testing.T) {
|
|||||||
etcdPrefix := s.RecommendedOptions.Etcd.StorageConfig.Prefix
|
etcdPrefix := s.RecommendedOptions.Etcd.StorageConfig.Prefix
|
||||||
|
|
||||||
ns1 := "another-default-is-possible"
|
ns1 := "another-default-is-possible"
|
||||||
curletDefinition := fixtures.NewCurletCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
curletDefinition := fixtures.NewCurletV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||||
curletDefinition, err = fixtures.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient)
|
curletDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -338,8 +338,8 @@ func TestEtcdStorage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ns2 := "the-cruel-default"
|
ns2 := "the-cruel-default"
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -23,15 +23,14 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
|
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/client-go/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
|
|
||||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
|
||||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHandlerScope(t *testing.T) {
|
func TestHandlerScope(t *testing.T) {
|
||||||
@ -41,15 +40,32 @@ func TestHandlerScope(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
for _, scope := range []apiextensionsv1beta1.ResourceScope{apiextensionsv1beta1.ClusterScoped, apiextensionsv1beta1.NamespaceScoped} {
|
for _, scope := range []apiextensionsv1.ResourceScope{apiextensionsv1.ClusterScoped, apiextensionsv1.NamespaceScoped} {
|
||||||
t.Run(string(scope), func(t *testing.T) {
|
t.Run(string(scope), func(t *testing.T) {
|
||||||
|
|
||||||
crd := &apiextensionsv1beta1.CustomResourceDefinition{
|
crd := &apiextensionsv1.CustomResourceDefinition{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: strings.ToLower(string(scope)) + "s.test.apiextensions-apiserver.k8s.io"},
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
Name: strings.ToLower(string(scope)) + "s.test.apiextensions-apiserver.k8s.io",
|
||||||
Group: "test.apiextensions-apiserver.k8s.io",
|
Annotations: map[string]string{"api-approved.kubernetes.io": "unapproved, test-only"},
|
||||||
Version: "v1beta1",
|
},
|
||||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||||
|
Group: "test.apiextensions-apiserver.k8s.io",
|
||||||
|
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||||
|
{
|
||||||
|
Name: "v1beta1",
|
||||||
|
Served: true,
|
||||||
|
Storage: true,
|
||||||
|
Subresources: &apiextensionsv1.CustomResourceSubresources{
|
||||||
|
Status: &apiextensionsv1.CustomResourceSubresourceStatus{},
|
||||||
|
Scale: &apiextensionsv1.CustomResourceSubresourceScale{
|
||||||
|
SpecReplicasPath: ".spec.replicas",
|
||||||
|
StatusReplicasPath: ".status.replicas",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Schema: fixtures.AllowAllSchema(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||||
Plural: strings.ToLower(string(scope)) + "s",
|
Plural: strings.ToLower(string(scope)) + "s",
|
||||||
Singular: strings.ToLower(string(scope)),
|
Singular: strings.ToLower(string(scope)),
|
||||||
Kind: string(scope),
|
Kind: string(scope),
|
||||||
@ -58,14 +74,7 @@ func TestHandlerScope(t *testing.T) {
|
|||||||
Scope: scope,
|
Scope: scope,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
crd.Spec.Subresources = &apiextensionsv1beta1.CustomResourceSubresources{
|
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||||
Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{},
|
|
||||||
Scale: &apiextensionsv1beta1.CustomResourceSubresourceScale{
|
|
||||||
SpecReplicasPath: ".spec.replicas",
|
|
||||||
StatusReplicasPath: ".status.replicas",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -75,7 +84,7 @@ func TestHandlerScope(t *testing.T) {
|
|||||||
ns := "test"
|
ns := "test"
|
||||||
var client dynamic.ResourceInterface = dynamicClient.Resource(gvr)
|
var client dynamic.ResourceInterface = dynamicClient.Resource(gvr)
|
||||||
var otherScopeClient dynamic.ResourceInterface = dynamicClient.Resource(gvr).Namespace(ns)
|
var otherScopeClient dynamic.ResourceInterface = dynamicClient.Resource(gvr).Namespace(ns)
|
||||||
if crd.Spec.Scope == apiextensionsv1beta1.NamespaceScoped {
|
if crd.Spec.Scope == apiextensionsv1.NamespaceScoped {
|
||||||
client, otherScopeClient = otherScopeClient, client
|
client, otherScopeClient = otherScopeClient, client
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +150,7 @@ func TestHandlerScope(t *testing.T) {
|
|||||||
err = otherScopeClient.DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{})
|
err = otherScopeClient.DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{})
|
||||||
assert.True(t, apierrors.IsNotFound(err))
|
assert.True(t, apierrors.IsNotFound(err))
|
||||||
|
|
||||||
if scope == apiextensionsv1beta1.ClusterScoped {
|
if scope == apiextensionsv1.ClusterScoped {
|
||||||
_, err = otherScopeClient.List(context.TODO(), metav1.ListOptions{})
|
_, err = otherScopeClient.List(context.TODO(), metav1.ListOptions{})
|
||||||
assert.True(t, apierrors.IsNotFound(err))
|
assert.True(t, apierrors.IsNotFound(err))
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ import (
|
|||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/client-go/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
|
|
||||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
)
|
)
|
||||||
@ -43,51 +43,14 @@ import (
|
|||||||
var labelSelectorPath = ".status.labelSelector"
|
var labelSelectorPath = ".status.labelSelector"
|
||||||
var anotherLabelSelectorPath = ".status.anotherLabelSelector"
|
var anotherLabelSelectorPath = ".status.anotherLabelSelector"
|
||||||
|
|
||||||
func NewNoxuSubresourcesCRDs(scope apiextensionsv1beta1.ResourceScope) []*apiextensionsv1beta1.CustomResourceDefinition {
|
func NewNoxuSubresourcesCRDs(scope apiextensionsv1.ResourceScope) []*apiextensionsv1.CustomResourceDefinition {
|
||||||
return []*apiextensionsv1beta1.CustomResourceDefinition{
|
return []*apiextensionsv1.CustomResourceDefinition{
|
||||||
// CRD that uses top-level subresources
|
|
||||||
{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"},
|
|
||||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
|
||||||
Group: "mygroup.example.com",
|
|
||||||
Version: "v1beta1",
|
|
||||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
|
||||||
Plural: "noxus",
|
|
||||||
Singular: "nonenglishnoxu",
|
|
||||||
Kind: "WishIHadChosenNoxu",
|
|
||||||
ShortNames: []string{"foo", "bar", "abc", "def"},
|
|
||||||
ListKind: "NoxuItemList",
|
|
||||||
},
|
|
||||||
Scope: scope,
|
|
||||||
Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{
|
|
||||||
{
|
|
||||||
Name: "v1beta1",
|
|
||||||
Served: true,
|
|
||||||
Storage: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "v1",
|
|
||||||
Served: true,
|
|
||||||
Storage: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Subresources: &apiextensionsv1beta1.CustomResourceSubresources{
|
|
||||||
Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{},
|
|
||||||
Scale: &apiextensionsv1beta1.CustomResourceSubresourceScale{
|
|
||||||
SpecReplicasPath: ".spec.replicas",
|
|
||||||
StatusReplicasPath: ".status.replicas",
|
|
||||||
LabelSelectorPath: &labelSelectorPath,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// CRD that uses per-version subresources
|
// CRD that uses per-version subresources
|
||||||
{
|
{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"},
|
ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"},
|
||||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||||
Group: "mygroup.example.com",
|
Group: "mygroup.example.com",
|
||||||
Version: "v1beta1",
|
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
|
||||||
Plural: "noxus",
|
Plural: "noxus",
|
||||||
Singular: "nonenglishnoxu",
|
Singular: "nonenglishnoxu",
|
||||||
Kind: "WishIHadChosenNoxu",
|
Kind: "WishIHadChosenNoxu",
|
||||||
@ -95,32 +58,34 @@ func NewNoxuSubresourcesCRDs(scope apiextensionsv1beta1.ResourceScope) []*apiext
|
|||||||
ListKind: "NoxuItemList",
|
ListKind: "NoxuItemList",
|
||||||
},
|
},
|
||||||
Scope: scope,
|
Scope: scope,
|
||||||
Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{
|
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||||
{
|
{
|
||||||
Name: "v1beta1",
|
Name: "v1beta1",
|
||||||
Served: true,
|
Served: true,
|
||||||
Storage: true,
|
Storage: true,
|
||||||
Subresources: &apiextensionsv1beta1.CustomResourceSubresources{
|
Subresources: &apiextensionsv1.CustomResourceSubresources{
|
||||||
Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{},
|
Status: &apiextensionsv1.CustomResourceSubresourceStatus{},
|
||||||
Scale: &apiextensionsv1beta1.CustomResourceSubresourceScale{
|
Scale: &apiextensionsv1.CustomResourceSubresourceScale{
|
||||||
SpecReplicasPath: ".spec.replicas",
|
SpecReplicasPath: ".spec.replicas",
|
||||||
StatusReplicasPath: ".status.replicas",
|
StatusReplicasPath: ".status.replicas",
|
||||||
LabelSelectorPath: &labelSelectorPath,
|
LabelSelectorPath: &labelSelectorPath,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Schema: fixtures.AllowAllSchema(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "v1",
|
Name: "v1",
|
||||||
Served: true,
|
Served: true,
|
||||||
Storage: false,
|
Storage: false,
|
||||||
Subresources: &apiextensionsv1beta1.CustomResourceSubresources{
|
Subresources: &apiextensionsv1.CustomResourceSubresources{
|
||||||
Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{},
|
Status: &apiextensionsv1.CustomResourceSubresourceStatus{},
|
||||||
Scale: &apiextensionsv1beta1.CustomResourceSubresourceScale{
|
Scale: &apiextensionsv1.CustomResourceSubresourceScale{
|
||||||
SpecReplicasPath: ".spec.replicas",
|
SpecReplicasPath: ".spec.replicas",
|
||||||
StatusReplicasPath: ".status.replicas",
|
StatusReplicasPath: ".status.replicas",
|
||||||
LabelSelectorPath: &anotherLabelSelectorPath,
|
LabelSelectorPath: &anotherLabelSelectorPath,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Schema: fixtures.AllowAllSchema(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -155,9 +120,9 @@ func TestStatusSubresource(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped)
|
||||||
for _, noxuDefinition := range noxuDefinitions {
|
for _, noxuDefinition := range noxuDefinitions {
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -254,7 +219,7 @@ func TestStatusSubresource(t *testing.T) {
|
|||||||
}
|
}
|
||||||
noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{})
|
noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{})
|
||||||
}
|
}
|
||||||
if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -281,7 +246,7 @@ func TestScaleSubresource(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped)
|
||||||
for _, noxuDefinition := range noxuDefinitions {
|
for _, noxuDefinition := range noxuDefinitions {
|
||||||
for _, v := range noxuDefinition.Spec.Versions {
|
for _, v := range noxuDefinition.Spec.Versions {
|
||||||
// Start with a new CRD, so that the object doesn't have resourceVersion
|
// Start with a new CRD, so that the object doesn't have resourceVersion
|
||||||
@ -293,13 +258,13 @@ func TestScaleSubresource(t *testing.T) {
|
|||||||
}
|
}
|
||||||
// set invalid json path for specReplicasPath
|
// set invalid json path for specReplicasPath
|
||||||
subresources.Scale.SpecReplicasPath = "foo,bar"
|
subresources.Scale.SpecReplicasPath = "foo,bar"
|
||||||
_, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
_, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("unexpected non-error: specReplicasPath should be a valid json path under .spec")
|
t.Fatalf("unexpected non-error: specReplicasPath should be a valid json path under .spec")
|
||||||
}
|
}
|
||||||
|
|
||||||
subresources.Scale.SpecReplicasPath = ".spec.replicas"
|
subresources.Scale.SpecReplicasPath = ".spec.replicas"
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -400,7 +365,7 @@ func TestScaleSubresource(t *testing.T) {
|
|||||||
t.Fatalf("unexpected non-error: .spec.replicas should be less than 2147483647")
|
t.Fatalf("unexpected non-error: .spec.replicas should be less than 2147483647")
|
||||||
}
|
}
|
||||||
noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{})
|
noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{})
|
||||||
if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,22 +388,16 @@ func TestValidationSchemaWithStatus(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// fields other than properties in root schema are not allowed
|
noxuDefinition := newNoxuValidationCRDs()[0]
|
||||||
noxuDefinition := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped)[0]
|
|
||||||
noxuDefinition.Spec.Subresources = &apiextensionsv1beta1.CustomResourceSubresources{
|
|
||||||
Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{},
|
|
||||||
}
|
|
||||||
_, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatalf(`unexpected non-error, expected: must not have "additionalProperties" at the root of the schema if the status subresource is enabled`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure we are not restricting fields to properties even in subschemas
|
// make sure we are not restricting fields to properties even in subschemas
|
||||||
noxuDefinition.Spec.Validation.OpenAPIV3Schema = &apiextensionsv1beta1.JSONSchemaProps{
|
noxuDefinition.Spec.Versions[0].Schema.OpenAPIV3Schema = &apiextensionsv1.JSONSchemaProps{
|
||||||
Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
|
Type: "object",
|
||||||
|
Properties: map[string]apiextensionsv1.JSONSchemaProps{
|
||||||
"spec": {
|
"spec": {
|
||||||
|
Type: "object",
|
||||||
Description: "Validation for spec",
|
Description: "Validation for spec",
|
||||||
Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
|
Properties: map[string]apiextensionsv1.JSONSchemaProps{
|
||||||
"replicas": {
|
"replicas": {
|
||||||
Type: "integer",
|
Type: "integer",
|
||||||
},
|
},
|
||||||
@ -448,7 +407,9 @@ func TestValidationSchemaWithStatus(t *testing.T) {
|
|||||||
Required: []string{"spec"},
|
Required: []string{"spec"},
|
||||||
Description: "This is a description at the root of the schema",
|
Description: "This is a description at the root of the schema",
|
||||||
}
|
}
|
||||||
_, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition.Spec.Versions[1].Schema.OpenAPIV3Schema = noxuDefinition.Spec.Versions[0].Schema.OpenAPIV3Schema
|
||||||
|
|
||||||
|
_, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to created crd %v: %v", noxuDefinition.Name, err)
|
t.Fatalf("unable to created crd %v: %v", noxuDefinition.Name, err)
|
||||||
}
|
}
|
||||||
@ -468,10 +429,12 @@ func TestValidateOnlyStatus(t *testing.T) {
|
|||||||
// 4. update the spec of the cr with .spec.num = 15 (spec is invalid), expect error
|
// 4. update the spec of the cr with .spec.num = 15 (spec is invalid), expect error
|
||||||
|
|
||||||
// max value of spec.num = 10 and status.num = 10
|
// max value of spec.num = 10 and status.num = 10
|
||||||
schema := &apiextensionsv1beta1.JSONSchemaProps{
|
schema := &apiextensionsv1.JSONSchemaProps{
|
||||||
Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
|
Type: "object",
|
||||||
|
Properties: map[string]apiextensionsv1.JSONSchemaProps{
|
||||||
"spec": {
|
"spec": {
|
||||||
Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
|
Type: "object",
|
||||||
|
Properties: map[string]apiextensionsv1.JSONSchemaProps{
|
||||||
"num": {
|
"num": {
|
||||||
Type: "integer",
|
Type: "integer",
|
||||||
Maximum: float64Ptr(10),
|
Maximum: float64Ptr(10),
|
||||||
@ -479,7 +442,8 @@ func TestValidateOnlyStatus(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
|
Type: "object",
|
||||||
|
Properties: map[string]apiextensionsv1.JSONSchemaProps{
|
||||||
"num": {
|
"num": {
|
||||||
Type: "integer",
|
Type: "integer",
|
||||||
Maximum: float64Ptr(10),
|
Maximum: float64Ptr(10),
|
||||||
@ -489,24 +453,16 @@ func TestValidateOnlyStatus(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped)
|
||||||
for i, noxuDefinition := range noxuDefinitions {
|
for _, noxuDefinition := range noxuDefinitions {
|
||||||
if i == 0 {
|
noxuDefinition.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{
|
||||||
noxuDefinition.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{
|
OpenAPIV3Schema: schema.DeepCopy(),
|
||||||
OpenAPIV3Schema: schema,
|
}
|
||||||
}
|
noxuDefinition.Spec.Versions[1].Schema = &apiextensionsv1.CustomResourceValidation{
|
||||||
} else {
|
OpenAPIV3Schema: schema.DeepCopy(),
|
||||||
noxuDefinition.Spec.Versions[0].Schema = &apiextensionsv1beta1.CustomResourceValidation{
|
|
||||||
OpenAPIV3Schema: schema,
|
|
||||||
}
|
|
||||||
schemaWithDescription := schema.DeepCopy()
|
|
||||||
schemaWithDescription.Description = "test"
|
|
||||||
noxuDefinition.Spec.Versions[1].Schema = &apiextensionsv1beta1.CustomResourceValidation{
|
|
||||||
OpenAPIV3Schema: schemaWithDescription,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -554,7 +510,7 @@ func TestValidateOnlyStatus(t *testing.T) {
|
|||||||
}
|
}
|
||||||
noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{})
|
noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{})
|
||||||
}
|
}
|
||||||
if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -576,9 +532,9 @@ func TestSubresourcesDiscovery(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped)
|
||||||
for _, noxuDefinition := range noxuDefinitions {
|
for _, noxuDefinition := range noxuDefinitions {
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -645,7 +601,7 @@ func TestSubresourcesDiscovery(t *testing.T) {
|
|||||||
t.Fatalf("incorrect scale via discovery: expected: %v, got: %v", expectedVerbs, scale.Verbs)
|
t.Fatalf("incorrect scale via discovery: expected: %v, got: %v", expectedVerbs, scale.Verbs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -658,9 +614,9 @@ func TestGeneration(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped)
|
||||||
for _, noxuDefinition := range noxuDefinitions {
|
for _, noxuDefinition := range noxuDefinitions {
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -718,7 +674,7 @@ func TestGeneration(t *testing.T) {
|
|||||||
}
|
}
|
||||||
noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{})
|
noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{})
|
||||||
}
|
}
|
||||||
if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -745,9 +701,9 @@ func TestSubresourcePatch(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped)
|
||||||
for _, noxuDefinition := range noxuDefinitions {
|
for _, noxuDefinition := range noxuDefinitions {
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -882,7 +838,7 @@ func TestSubresourcePatch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{})
|
noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{})
|
||||||
}
|
}
|
||||||
if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,42 +32,42 @@ import (
|
|||||||
"k8s.io/client-go/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
|
|
||||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newTableCRD() *apiextensionsv1beta1.CustomResourceDefinition {
|
func newTableCRD() *apiextensionsv1.CustomResourceDefinition {
|
||||||
return &apiextensionsv1beta1.CustomResourceDefinition{
|
return &apiextensionsv1.CustomResourceDefinition{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "tables.mygroup.example.com"},
|
ObjectMeta: metav1.ObjectMeta{Name: "tables.mygroup.example.com"},
|
||||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||||
Group: "mygroup.example.com",
|
Group: "mygroup.example.com",
|
||||||
Version: "v1beta1",
|
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
|
||||||
Plural: "tables",
|
Plural: "tables",
|
||||||
Singular: "table",
|
Singular: "table",
|
||||||
Kind: "Table",
|
Kind: "Table",
|
||||||
ListKind: "TablemList",
|
ListKind: "TablemList",
|
||||||
},
|
},
|
||||||
Scope: apiextensionsv1beta1.ClusterScoped,
|
Scope: apiextensionsv1.ClusterScoped,
|
||||||
Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{
|
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||||
{
|
{
|
||||||
Name: "v1beta1",
|
Name: "v1beta1",
|
||||||
Served: true,
|
Served: true,
|
||||||
Storage: false,
|
Storage: false,
|
||||||
AdditionalPrinterColumns: []apiextensionsv1beta1.CustomResourceColumnDefinition{
|
AdditionalPrinterColumns: []apiextensionsv1.CustomResourceColumnDefinition{
|
||||||
{Name: "Age", Type: "date", JSONPath: ".metadata.creationTimestamp"},
|
{Name: "Age", Type: "date", JSONPath: ".metadata.creationTimestamp"},
|
||||||
{Name: "Alpha", Type: "string", JSONPath: ".spec.alpha"},
|
{Name: "Alpha", Type: "string", JSONPath: ".spec.alpha"},
|
||||||
{Name: "Beta", Type: "integer", Description: "the beta field", Format: "int64", Priority: 42, JSONPath: ".spec.beta"},
|
{Name: "Beta", Type: "integer", Description: "the beta field", Format: "int64", Priority: 42, JSONPath: ".spec.beta"},
|
||||||
{Name: "Gamma", Type: "integer", Description: "a column with wrongly typed values", JSONPath: ".spec.gamma"},
|
{Name: "Gamma", Type: "integer", Description: "a column with wrongly typed values", JSONPath: ".spec.gamma"},
|
||||||
{Name: "Epsilon", Type: "string", Description: "an array of integers as string", JSONPath: ".spec.epsilon"},
|
{Name: "Epsilon", Type: "string", Description: "an array of integers as string", JSONPath: ".spec.epsilon"},
|
||||||
},
|
},
|
||||||
|
Schema: fixtures.AllowAllSchema(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "v1",
|
Name: "v1",
|
||||||
Served: true,
|
Served: true,
|
||||||
Storage: true,
|
Storage: true,
|
||||||
AdditionalPrinterColumns: []apiextensionsv1beta1.CustomResourceColumnDefinition{
|
AdditionalPrinterColumns: []apiextensionsv1.CustomResourceColumnDefinition{
|
||||||
{Name: "Age", Type: "date", JSONPath: ".metadata.creationTimestamp"},
|
{Name: "Age", Type: "date", JSONPath: ".metadata.creationTimestamp"},
|
||||||
{Name: "Alpha", Type: "string", JSONPath: ".spec.alpha"},
|
{Name: "Alpha", Type: "string", JSONPath: ".spec.alpha"},
|
||||||
{Name: "Beta", Type: "integer", Description: "the beta field", Format: "int64", Priority: 42, JSONPath: ".spec.beta"},
|
{Name: "Beta", Type: "integer", Description: "the beta field", Format: "int64", Priority: 42, JSONPath: ".spec.beta"},
|
||||||
@ -75,6 +75,7 @@ func newTableCRD() *apiextensionsv1beta1.CustomResourceDefinition {
|
|||||||
{Name: "Epsilon", Type: "string", Description: "an array of integers as string", JSONPath: ".spec.epsilon"},
|
{Name: "Epsilon", Type: "string", Description: "an array of integers as string", JSONPath: ".spec.epsilon"},
|
||||||
{Name: "Zeta", Type: "integer", Description: "the zeta field", Format: "int64", Priority: 42, JSONPath: ".spec.zeta"},
|
{Name: "Zeta", Type: "integer", Description: "the zeta field", Format: "int64", Priority: 42, JSONPath: ".spec.zeta"},
|
||||||
},
|
},
|
||||||
|
Schema: fixtures.AllowAllSchema(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -119,12 +120,12 @@ func TestTableGet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
crd := newTableCRD()
|
crd := newTableCRD()
|
||||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
crd, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{})
|
crd, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -377,8 +378,8 @@ func TestColumnsPatch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CRD with no top-level and per-version columns should be created successfully
|
// CRD with no top-level and per-version columns should be created successfully
|
||||||
crd := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped)[0]
|
crd := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped)[0]
|
||||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -386,14 +387,50 @@ func TestColumnsPatch(t *testing.T) {
|
|||||||
// One should be able to patch the CRD to use per-version columns. The top-level columns
|
// One should be able to patch the CRD to use per-version columns. The top-level columns
|
||||||
// should not be defaulted during creation, and apiserver should not return validation
|
// should not be defaulted during creation, and apiserver should not return validation
|
||||||
// error about top-level and per-version columns being mutual exclusive.
|
// error about top-level and per-version columns being mutual exclusive.
|
||||||
patch := []byte(`{"spec":{"versions":[{"name":"v1beta1","served":true,"storage":true,"additionalPrinterColumns":[{"name":"Age","type":"date","JSONPath":".metadata.creationTimestamp"}]},{"name":"v1","served":true,"storage":false,"additionalPrinterColumns":[{"name":"Age2","type":"date","JSONPath":".metadata.creationTimestamp"}]}]}}`)
|
patch := []byte(`{
|
||||||
|
"spec": {
|
||||||
|
"versions": [
|
||||||
|
{
|
||||||
|
"name": "v1beta1",
|
||||||
|
"served": true,
|
||||||
|
"storage": true,
|
||||||
|
"additionalPrinterColumns": [
|
||||||
|
{
|
||||||
|
"name": "Age",
|
||||||
|
"type": "date",
|
||||||
|
"jsonPath": ".metadata.creationTimestamp"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"openAPIV3Schema": {"x-kubernetes-preserve-unknown-fields": true, "type": "object"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "v1",
|
||||||
|
"served": true,
|
||||||
|
"storage": false,
|
||||||
|
"additionalPrinterColumns": [
|
||||||
|
{
|
||||||
|
"name": "Age2",
|
||||||
|
"type": "date",
|
||||||
|
"jsonPath": ".metadata.creationTimestamp"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"openAPIV3Schema": {"x-kubernetes-preserve-unknown-fields": true, "type": "object"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
_, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Patch(context.TODO(), crd.Name, types.MergePatchType, patch, metav1.PatchOptions{})
|
_, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Patch(context.TODO(), crd.Name, types.MergePatchType, patch, metav1.PatchOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
crd, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{})
|
crd, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -420,11 +457,11 @@ func TestPatchCleanTopLevelColumns(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
crd := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped)[0]
|
crd := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped)[0]
|
||||||
crd.Spec.AdditionalPrinterColumns = []apiextensionsv1beta1.CustomResourceColumnDefinition{
|
crd.Spec.Versions[0].AdditionalPrinterColumns = []apiextensionsv1.CustomResourceColumnDefinition{
|
||||||
{Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"},
|
{Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"},
|
||||||
}
|
}
|
||||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -432,14 +469,51 @@ func TestPatchCleanTopLevelColumns(t *testing.T) {
|
|||||||
|
|
||||||
// One should be able to patch the CRD to use per-version columns by cleaning
|
// One should be able to patch the CRD to use per-version columns by cleaning
|
||||||
// the top-level columns.
|
// the top-level columns.
|
||||||
patch := []byte(`{"spec":{"additionalPrinterColumns":null,"versions":[{"name":"v1beta1","served":true,"storage":true,"additionalPrinterColumns":[{"name":"Age","type":"date","JSONPath":".metadata.creationTimestamp"}]},{"name":"v1","served":true,"storage":false,"additionalPrinterColumns":[{"name":"Age2","type":"date","JSONPath":".metadata.creationTimestamp"}]}]}}`)
|
patch := []byte(`{
|
||||||
|
"spec": {
|
||||||
|
"additionalPrinterColumns": null,
|
||||||
|
"versions": [
|
||||||
|
{
|
||||||
|
"name": "v1beta1",
|
||||||
|
"served": true,
|
||||||
|
"storage": true,
|
||||||
|
"additionalPrinterColumns": [
|
||||||
|
{
|
||||||
|
"name": "Age",
|
||||||
|
"type": "date",
|
||||||
|
"jsonPath": ".metadata.creationTimestamp"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"openAPIV3Schema": {"x-kubernetes-preserve-unknown-fields": true, "type": "object"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "v1",
|
||||||
|
"served": true,
|
||||||
|
"storage": false,
|
||||||
|
"additionalPrinterColumns": [
|
||||||
|
{
|
||||||
|
"name": "Age2",
|
||||||
|
"type": "date",
|
||||||
|
"jsonPath": ".metadata.creationTimestamp"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"schema": {
|
||||||
|
"openAPIV3Schema": {"x-kubernetes-preserve-unknown-fields": true, "type": "object"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
_, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Patch(context.TODO(), crd.Name, types.MergePatchType, patch, metav1.PatchOptions{})
|
_, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Patch(context.TODO(), crd.Name, types.MergePatchType, patch, metav1.PatchOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
crd, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{})
|
crd, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ package integration
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -27,9 +28,10 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/util/json"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apimachinery/pkg/util/yaml"
|
"k8s.io/apimachinery/pkg/util/yaml"
|
||||||
|
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||||
|
|
||||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||||
@ -44,8 +46,8 @@ func TestForProperValidationErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -91,13 +93,11 @@ func TestForProperValidationErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newNoxuValidationCRDs(scope apiextensionsv1beta1.ResourceScope) []*apiextensionsv1beta1.CustomResourceDefinition {
|
func newNoxuValidationCRDs() []*apiextensionsv1.CustomResourceDefinition {
|
||||||
validationSchema := &apiextensionsv1beta1.JSONSchemaProps{
|
validationSchema := &apiextensionsv1.JSONSchemaProps{
|
||||||
|
Type: "object",
|
||||||
Required: []string{"alpha", "beta"},
|
Required: []string{"alpha", "beta"},
|
||||||
AdditionalProperties: &apiextensionsv1beta1.JSONSchemaPropsOrBool{
|
Properties: map[string]apiextensionsv1.JSONSchemaProps{
|
||||||
Allows: true,
|
|
||||||
},
|
|
||||||
Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
|
|
||||||
"alpha": {
|
"alpha": {
|
||||||
Description: "Alpha is an alphanumeric string with underscores",
|
Description: "Alpha is an alphanumeric string with underscores",
|
||||||
Type: "string",
|
Type: "string",
|
||||||
@ -111,7 +111,7 @@ func newNoxuValidationCRDs(scope apiextensionsv1beta1.ResourceScope) []*apiexten
|
|||||||
"gamma": {
|
"gamma": {
|
||||||
Description: "Gamma is restricted to foo, bar and baz",
|
Description: "Gamma is restricted to foo, bar and baz",
|
||||||
Type: "string",
|
Type: "string",
|
||||||
Enum: []apiextensionsv1beta1.JSON{
|
Enum: []apiextensionsv1.JSON{
|
||||||
{
|
{
|
||||||
Raw: []byte(`"foo"`),
|
Raw: []byte(`"foo"`),
|
||||||
},
|
},
|
||||||
@ -123,73 +123,29 @@ func newNoxuValidationCRDs(scope apiextensionsv1beta1.ResourceScope) []*apiexten
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"delta": {
|
|
||||||
Description: "Delta is a string with a maximum length of 5 or a number with a minimum value of 0",
|
|
||||||
AnyOf: []apiextensionsv1beta1.JSONSchemaProps{
|
|
||||||
{
|
|
||||||
Type: "string",
|
|
||||||
MaxLength: int64Ptr(5),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Type: "number",
|
|
||||||
Minimum: float64Ptr(0),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
validationSchemaWithDescription := validationSchema.DeepCopy()
|
validationSchemaWithDescription := validationSchema.DeepCopy()
|
||||||
validationSchemaWithDescription.Description = "test"
|
validationSchemaWithDescription.Description = "test"
|
||||||
return []*apiextensionsv1beta1.CustomResourceDefinition{
|
return []*apiextensionsv1.CustomResourceDefinition{
|
||||||
{
|
{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"},
|
ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"},
|
||||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||||
Group: "mygroup.example.com",
|
Group: "mygroup.example.com",
|
||||||
Version: "v1beta1",
|
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
|
||||||
Plural: "noxus",
|
Plural: "noxus",
|
||||||
Singular: "nonenglishnoxu",
|
Singular: "nonenglishnoxu",
|
||||||
Kind: "WishIHadChosenNoxu",
|
Kind: "WishIHadChosenNoxu",
|
||||||
ShortNames: []string{"foo", "bar", "abc", "def"},
|
ShortNames: []string{"foo", "bar", "abc", "def"},
|
||||||
ListKind: "NoxuItemList",
|
ListKind: "NoxuItemList",
|
||||||
},
|
},
|
||||||
Scope: apiextensionsv1beta1.NamespaceScoped,
|
Scope: apiextensionsv1.NamespaceScoped,
|
||||||
Validation: &apiextensionsv1beta1.CustomResourceValidation{
|
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||||
OpenAPIV3Schema: validationSchema,
|
|
||||||
},
|
|
||||||
Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{
|
|
||||||
{
|
{
|
||||||
Name: "v1beta1",
|
Name: "v1beta1",
|
||||||
Served: true,
|
Served: true,
|
||||||
Storage: true,
|
Storage: true,
|
||||||
},
|
Schema: &apiextensionsv1.CustomResourceValidation{
|
||||||
{
|
|
||||||
Name: "v1",
|
|
||||||
Served: true,
|
|
||||||
Storage: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"},
|
|
||||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
|
||||||
Group: "mygroup.example.com",
|
|
||||||
Version: "v1beta1",
|
|
||||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
|
||||||
Plural: "noxus",
|
|
||||||
Singular: "nonenglishnoxu",
|
|
||||||
Kind: "WishIHadChosenNoxu",
|
|
||||||
ShortNames: []string{"foo", "bar", "abc", "def"},
|
|
||||||
ListKind: "NoxuItemList",
|
|
||||||
},
|
|
||||||
Scope: apiextensionsv1beta1.NamespaceScoped,
|
|
||||||
Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{
|
|
||||||
{
|
|
||||||
Name: "v1beta1",
|
|
||||||
Served: true,
|
|
||||||
Storage: true,
|
|
||||||
Schema: &apiextensionsv1beta1.CustomResourceValidation{
|
|
||||||
OpenAPIV3Schema: validationSchema,
|
OpenAPIV3Schema: validationSchema,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -197,7 +153,39 @@ func newNoxuValidationCRDs(scope apiextensionsv1beta1.ResourceScope) []*apiexten
|
|||||||
Name: "v1",
|
Name: "v1",
|
||||||
Served: true,
|
Served: true,
|
||||||
Storage: false,
|
Storage: false,
|
||||||
Schema: &apiextensionsv1beta1.CustomResourceValidation{
|
Schema: &apiextensionsv1.CustomResourceValidation{
|
||||||
|
OpenAPIV3Schema: validationSchema,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"},
|
||||||
|
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||||
|
Group: "mygroup.example.com",
|
||||||
|
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||||
|
Plural: "noxus",
|
||||||
|
Singular: "nonenglishnoxu",
|
||||||
|
Kind: "WishIHadChosenNoxu",
|
||||||
|
ShortNames: []string{"foo", "bar", "abc", "def"},
|
||||||
|
ListKind: "NoxuItemList",
|
||||||
|
},
|
||||||
|
Scope: apiextensionsv1.NamespaceScoped,
|
||||||
|
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||||
|
{
|
||||||
|
Name: "v1beta1",
|
||||||
|
Served: true,
|
||||||
|
Storage: true,
|
||||||
|
Schema: &apiextensionsv1.CustomResourceValidation{
|
||||||
|
OpenAPIV3Schema: validationSchema,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "v1",
|
||||||
|
Served: true,
|
||||||
|
Storage: false,
|
||||||
|
Schema: &apiextensionsv1.CustomResourceValidation{
|
||||||
OpenAPIV3Schema: validationSchemaWithDescription,
|
OpenAPIV3Schema: validationSchemaWithDescription,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -231,9 +219,9 @@ func TestCustomResourceValidation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinitions := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinitions := newNoxuValidationCRDs()
|
||||||
for _, noxuDefinition := range noxuDefinitions {
|
for _, noxuDefinition := range noxuDefinitions {
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -249,7 +237,7 @@ func TestCustomResourceValidation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{})
|
noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{})
|
||||||
}
|
}
|
||||||
if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -436,9 +424,9 @@ func TestCustomResourceUpdateValidation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinitions := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinitions := newNoxuValidationCRDs()
|
||||||
for _, noxuDefinition := range noxuDefinitions {
|
for _, noxuDefinition := range noxuDefinitions {
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -476,7 +464,7 @@ func TestCustomResourceUpdateValidation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{})
|
noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{})
|
||||||
}
|
}
|
||||||
if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -489,9 +477,9 @@ func TestCustomResourceValidationErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinitions := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinitions := newNoxuValidationCRDs()
|
||||||
for _, noxuDefinition := range noxuDefinitions {
|
for _, noxuDefinition := range noxuDefinitions {
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -530,18 +518,6 @@ func TestCustomResourceValidationErrors(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expectedErrors: []string{`gamma: Unsupported value: "qux": supported values: "foo", "bar", "baz"`},
|
expectedErrors: []string{`gamma: Unsupported value: "qux": supported values: "foo", "bar", "baz"`},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "bad delta",
|
|
||||||
instanceFn: func() *unstructured.Unstructured {
|
|
||||||
instance := newNoxuValidationInstance(ns, "foo")
|
|
||||||
instance.Object["delta"] = "foobarbaz"
|
|
||||||
return instance
|
|
||||||
},
|
|
||||||
expectedErrors: []string{
|
|
||||||
"must validate at least one schema (anyOf)",
|
|
||||||
"delta in body should be at most 5 chars long",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "absent alpha and beta",
|
name: "absent alpha and beta",
|
||||||
instanceFn: func() *unstructured.Unstructured {
|
instanceFn: func() *unstructured.Unstructured {
|
||||||
@ -580,7 +556,7 @@ func TestCustomResourceValidationErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -593,26 +569,27 @@ func TestCRValidationOnCRDUpdate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinitions := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinitions := newNoxuValidationCRDs()
|
||||||
for i, noxuDefinition := range noxuDefinitions {
|
for i, noxuDefinition := range noxuDefinitions {
|
||||||
for _, v := range noxuDefinition.Spec.Versions {
|
for _, v := range noxuDefinition.Spec.Versions {
|
||||||
// Re-define the CRD to make sure we start with a clean CRD
|
// Re-define the CRD to make sure we start with a clean CRD
|
||||||
noxuDefinition := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped)[i]
|
noxuDefinition := newNoxuValidationCRDs()[i]
|
||||||
validationSchema, err := getSchemaForVersion(noxuDefinition, v.Name)
|
validationSchema, err := getSchemaForVersion(noxuDefinition, v.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// set stricter schema
|
// set stricter schema
|
||||||
validationSchema.OpenAPIV3Schema.Required = []string{"alpha", "beta", "epsilon"}
|
validationSchema.OpenAPIV3Schema.Required = []string{"alpha", "beta", "gamma"}
|
||||||
|
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
ns := "not-the-default"
|
ns := "not-the-default"
|
||||||
noxuResourceClient := newNamespacedCustomResourceVersionedClient(ns, dynamicClient, noxuDefinition, v.Name)
|
noxuResourceClient := newNamespacedCustomResourceVersionedClient(ns, dynamicClient, noxuDefinition, v.Name)
|
||||||
instanceToCreate := newNoxuValidationInstance(ns, "foo")
|
instanceToCreate := newNoxuValidationInstance(ns, "foo")
|
||||||
|
unstructured.RemoveNestedField(instanceToCreate.Object, "gamma")
|
||||||
instanceToCreate.Object["apiVersion"] = fmt.Sprintf("%s/%s", noxuDefinition.Spec.Group, v.Name)
|
instanceToCreate.Object["apiVersion"] = fmt.Sprintf("%s/%s", noxuDefinition.Spec.Group, v.Name)
|
||||||
|
|
||||||
// CR is rejected
|
// CR is rejected
|
||||||
@ -622,7 +599,7 @@ func TestCRValidationOnCRDUpdate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update the CRD to a less stricter schema
|
// update the CRD to a less stricter schema
|
||||||
_, err = UpdateCustomResourceDefinitionWithRetry(apiExtensionClient, "noxus.mygroup.example.com", func(crd *apiextensionsv1beta1.CustomResourceDefinition) {
|
_, err = UpdateCustomResourceDefinitionWithRetry(apiExtensionClient, "noxus.mygroup.example.com", func(crd *apiextensionsv1.CustomResourceDefinition) {
|
||||||
validationSchema, err := getSchemaForVersion(crd, v.Name)
|
validationSchema, err := getSchemaForVersion(crd, v.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -650,7 +627,7 @@ func TestCRValidationOnCRDUpdate(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{})
|
noxuResourceClient.Delete(context.TODO(), "foo", metav1.DeleteOptions{})
|
||||||
if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -664,51 +641,59 @@ func TestForbiddenFieldsInSchema(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinitions := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinitions := newNoxuValidationCRDs()
|
||||||
for i, noxuDefinition := range noxuDefinitions {
|
for i, noxuDefinition := range noxuDefinitions {
|
||||||
for _, v := range noxuDefinition.Spec.Versions {
|
for _, v := range noxuDefinition.Spec.Versions {
|
||||||
// Re-define the CRD to make sure we start with a clean CRD
|
// Re-define the CRD to make sure we start with a clean CRD
|
||||||
noxuDefinition := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped)[i]
|
noxuDefinition := newNoxuValidationCRDs()[i]
|
||||||
validationSchema, err := getSchemaForVersion(noxuDefinition, v.Name)
|
validationSchema, err := getSchemaForVersion(noxuDefinition, v.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
validationSchema.OpenAPIV3Schema.AdditionalProperties.Allows = false
|
existingProperties := validationSchema.OpenAPIV3Schema.Properties
|
||||||
|
validationSchema.OpenAPIV3Schema.Properties = nil
|
||||||
_, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
validationSchema.OpenAPIV3Schema.AdditionalProperties = &apiextensionsv1.JSONSchemaPropsOrBool{Allows: false}
|
||||||
|
_, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("unexpected non-error: additionalProperties cannot be set to false")
|
t.Fatalf("unexpected non-error: additionalProperties cannot be set to false")
|
||||||
}
|
}
|
||||||
|
// reset
|
||||||
|
validationSchema.OpenAPIV3Schema.Properties = existingProperties
|
||||||
|
validationSchema.OpenAPIV3Schema.AdditionalProperties = nil
|
||||||
|
|
||||||
validationSchema.OpenAPIV3Schema.Properties["zeta"] = apiextensionsv1beta1.JSONSchemaProps{
|
validationSchema.OpenAPIV3Schema.Properties["zeta"] = apiextensionsv1.JSONSchemaProps{
|
||||||
Type: "array",
|
Type: "array",
|
||||||
UniqueItems: true,
|
UniqueItems: true,
|
||||||
|
AdditionalProperties: &apiextensionsv1.JSONSchemaPropsOrBool{
|
||||||
|
Allows: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
validationSchema.OpenAPIV3Schema.AdditionalProperties.Allows = true
|
_, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
|
|
||||||
_, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("unexpected non-error: uniqueItems cannot be set to true")
|
t.Fatalf("unexpected non-error: uniqueItems cannot be set to true")
|
||||||
}
|
}
|
||||||
|
|
||||||
validationSchema.OpenAPIV3Schema.Ref = strPtr("#/definition/zeta")
|
validationSchema.OpenAPIV3Schema.Ref = strPtr("#/definition/zeta")
|
||||||
validationSchema.OpenAPIV3Schema.Properties["zeta"] = apiextensionsv1beta1.JSONSchemaProps{
|
validationSchema.OpenAPIV3Schema.Properties["zeta"] = apiextensionsv1.JSONSchemaProps{
|
||||||
Type: "array",
|
Type: "array",
|
||||||
UniqueItems: false,
|
UniqueItems: false,
|
||||||
|
Items: &apiextensionsv1.JSONSchemaPropsOrArray{
|
||||||
|
Schema: &apiextensionsv1.JSONSchemaProps{Type: "object"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
_, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("unexpected non-error: $ref cannot be non-empty string")
|
t.Fatal("unexpected non-error: $ref cannot be non-empty string")
|
||||||
}
|
}
|
||||||
|
|
||||||
validationSchema.OpenAPIV3Schema.Ref = nil
|
validationSchema.OpenAPIV3Schema.Ref = nil
|
||||||
|
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -716,7 +701,7 @@ func TestForbiddenFieldsInSchema(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNonStructuralSchemaConditionUpdate(t *testing.T) {
|
func TestNonStructuralSchemaConditionUpdate(t *testing.T) {
|
||||||
tearDown, apiExtensionClient, _, err := fixtures.StartDefaultServerWithClients(t)
|
tearDown, apiExtensionClient, _, etcdclient, etcdStoragePrefix, err := fixtures.StartDefaultServerWithClientsAndEtcd(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -752,27 +737,37 @@ spec:
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed decoding of: %v\n\n%s", err, manifest)
|
t.Fatalf("failed decoding of: %v\n\n%s", err, manifest)
|
||||||
}
|
}
|
||||||
crd := obj.(*apiextensionsv1beta1.CustomResourceDefinition)
|
betaCRD := obj.(*apiextensionsv1beta1.CustomResourceDefinition)
|
||||||
name := crd.Name
|
name := betaCRD.Name
|
||||||
|
|
||||||
// save schema for later
|
// save schema for later
|
||||||
origSchema := crd.Spec.Validation.OpenAPIV3Schema
|
origSchema := &apiextensionsv1.JSONSchemaProps{
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]apiextensionsv1.JSONSchemaProps{
|
||||||
|
"a": {
|
||||||
|
Type: "object",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// create CRDs
|
// create CRDs. We cannot create these in v1, but they can exist in upgraded clusters
|
||||||
t.Logf("Creating CRD %s", crd.Name)
|
t.Logf("Creating CRD %s", betaCRD.Name)
|
||||||
if _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Create(context.TODO(), crd, metav1.CreateOptions{}); err != nil {
|
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceNone)
|
||||||
t.Fatalf("unexpected create error: %v", err)
|
key := path.Join("/", etcdStoragePrefix, "apiextensions.k8s.io", "customresourcedefinitions/foos.tests.example.com")
|
||||||
|
val, _ := json.Marshal(betaCRD)
|
||||||
|
if _, err := etcdclient.Put(ctx, key, string(val)); err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for condition with violations
|
// wait for condition with violations
|
||||||
t.Log("Waiting for NonStructuralSchema condition")
|
t.Log("Waiting for NonStructuralSchema condition")
|
||||||
var cond *apiextensionsv1beta1.CustomResourceDefinitionCondition
|
var cond *apiextensionsv1.CustomResourceDefinitionCondition
|
||||||
err = wait.PollImmediate(100*time.Millisecond, 5*time.Second, func() (bool, error) {
|
err = wait.PollImmediate(100*time.Millisecond, 5*time.Second, func() (bool, error) {
|
||||||
obj, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{})
|
obj, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
cond = findCRDCondition(obj, apiextensionsv1beta1.NonStructuralSchema)
|
cond = findCRDCondition(obj, apiextensionsv1.NonStructuralSchema)
|
||||||
return cond != nil, nil
|
return cond != nil, nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -785,34 +780,32 @@ spec:
|
|||||||
t.Fatalf("expected violation %q, but got: %v", v, cond.Message)
|
t.Fatalf("expected violation %q, but got: %v", v, cond.Message)
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove schema
|
t.Log("fix schema")
|
||||||
t.Log("Remove schema")
|
|
||||||
for retry := 0; retry < 5; retry++ {
|
for retry := 0; retry < 5; retry++ {
|
||||||
// This patch fixes two fields to resolve
|
crd, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{})
|
||||||
// 1. property type validation error
|
if err != nil {
|
||||||
// 2. preserveUnknownFields validation error
|
t.Fatal(err)
|
||||||
patch := []byte("[{\"op\":\"add\",\"path\":\"/spec/validation/openAPIV3Schema/properties/a/type\",\"value\":\"int\"}," +
|
}
|
||||||
"{\"op\":\"replace\",\"path\":\"/spec/preserveUnknownFields\",\"value\":false}]")
|
crd.Spec.Versions[0].Schema = fixtures.AllowAllSchema()
|
||||||
if _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Patch(context.TODO(), name, types.JSONPatchType, patch, metav1.PatchOptions{}); apierrors.IsConflict(err) {
|
crd.Spec.PreserveUnknownFields = false
|
||||||
|
_, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{})
|
||||||
|
if apierrors.IsConflict(err) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected update error: %v", err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected update error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for condition to go away
|
// wait for condition to go away
|
||||||
t.Log("Wait for condition to disappear")
|
t.Log("Wait for condition to disappear")
|
||||||
err = wait.PollImmediate(100*time.Millisecond, 5*time.Second, func() (bool, error) {
|
err = wait.PollImmediate(100*time.Millisecond, 5*time.Second, func() (bool, error) {
|
||||||
obj, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{})
|
obj, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
cond = findCRDCondition(obj, apiextensionsv1beta1.NonStructuralSchema)
|
cond = findCRDCondition(obj, apiextensionsv1.NonStructuralSchema)
|
||||||
return cond == nil, nil
|
return cond == nil, nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -822,43 +815,23 @@ spec:
|
|||||||
// re-add schema
|
// re-add schema
|
||||||
t.Log("Re-add schema")
|
t.Log("Re-add schema")
|
||||||
for retry := 0; retry < 5; retry++ {
|
for retry := 0; retry < 5; retry++ {
|
||||||
crd, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{})
|
crd, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected get error: %v", err)
|
t.Fatalf("unexpected get error: %v", err)
|
||||||
}
|
}
|
||||||
crd.Spec.PreserveUnknownFields = nil
|
crd.Spec.PreserveUnknownFields = true
|
||||||
crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{OpenAPIV3Schema: origSchema}
|
crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{OpenAPIV3Schema: origSchema}
|
||||||
if _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}); apierrors.IsConflict(err) {
|
if _, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}); apierrors.IsConflict(err) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err == nil {
|
||||||
t.Fatalf("unexpected update error: %v", err)
|
t.Fatalf("missing error")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "spec.preserveUnknownFields") {
|
||||||
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected update error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for condition with violations
|
|
||||||
t.Log("Wait for condition to reappear")
|
|
||||||
err = wait.PollImmediate(100*time.Millisecond, 5*time.Second, func() (bool, error) {
|
|
||||||
obj, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{})
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
cond = findCRDCondition(obj, apiextensionsv1beta1.NonStructuralSchema)
|
|
||||||
return cond != nil, nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error waiting for NonStructuralSchema condition: %v", cond)
|
|
||||||
}
|
|
||||||
if v := "spec.versions[0].schema.openAPIV3Schema.properties[a].type: Required value: must not be empty for specified object fields"; !strings.Contains(cond.Message, v) {
|
|
||||||
t.Fatalf("expected violation %q, but got: %v", v, cond.Message)
|
|
||||||
}
|
|
||||||
if v := "spec.preserveUnknownFields: Invalid value: true: must be false"; !strings.Contains(cond.Message, v) {
|
|
||||||
t.Fatalf("expected violation %q, but got: %v", v, cond.Message)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNonStructuralSchemaCondition(t *testing.T) {
|
func TestNonStructuralSchemaCondition(t *testing.T) {
|
||||||
@ -1657,13 +1630,13 @@ properties:
|
|||||||
|
|
||||||
if len(tst.expectedViolations) == 0 {
|
if len(tst.expectedViolations) == 0 {
|
||||||
// wait for condition to not appear
|
// wait for condition to not appear
|
||||||
var cond *apiextensionsv1beta1.CustomResourceDefinitionCondition
|
var cond *apiextensionsv1.CustomResourceDefinitionCondition
|
||||||
err := wait.PollImmediate(100*time.Millisecond, 5*time.Second, func() (bool, error) {
|
err := wait.PollImmediate(100*time.Millisecond, 5*time.Second, func() (bool, error) {
|
||||||
obj, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{})
|
obj, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
cond = findCRDCondition(obj, apiextensionsv1beta1.NonStructuralSchema)
|
cond = findCRDCondition(obj, apiextensionsv1.NonStructuralSchema)
|
||||||
if cond == nil {
|
if cond == nil {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
@ -1676,13 +1649,13 @@ properties:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// wait for condition to appear with the given violations
|
// wait for condition to appear with the given violations
|
||||||
var cond *apiextensionsv1beta1.CustomResourceDefinitionCondition
|
var cond *apiextensionsv1.CustomResourceDefinitionCondition
|
||||||
err = wait.PollImmediate(100*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) {
|
err = wait.PollImmediate(100*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) {
|
||||||
obj, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{})
|
obj, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), crd.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
cond = findCRDCondition(obj, apiextensionsv1beta1.NonStructuralSchema)
|
cond = findCRDCondition(obj, apiextensionsv1.NonStructuralSchema)
|
||||||
if cond != nil {
|
if cond != nil {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
@ -1696,7 +1669,7 @@ properties:
|
|||||||
if cond.Reason != "Violations" {
|
if cond.Reason != "Violations" {
|
||||||
t.Errorf("expected reason Violations, got: %v", cond.Reason)
|
t.Errorf("expected reason Violations, got: %v", cond.Reason)
|
||||||
}
|
}
|
||||||
if cond.Status != apiextensionsv1beta1.ConditionTrue {
|
if cond.Status != apiextensionsv1.ConditionTrue {
|
||||||
t.Errorf("expected reason True, got: %v", cond.Status)
|
t.Errorf("expected reason True, got: %v", cond.Status)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1717,7 +1690,7 @@ properties:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// findCRDCondition returns the condition you're looking for or nil.
|
// findCRDCondition returns the condition you're looking for or nil.
|
||||||
func findCRDCondition(crd *apiextensionsv1beta1.CustomResourceDefinition, conditionType apiextensionsv1beta1.CustomResourceDefinitionConditionType) *apiextensionsv1beta1.CustomResourceDefinitionCondition {
|
func findCRDCondition(crd *apiextensionsv1.CustomResourceDefinition, conditionType apiextensionsv1.CustomResourceDefinitionConditionType) *apiextensionsv1.CustomResourceDefinitionCondition {
|
||||||
for i := range crd.Status.Conditions {
|
for i := range crd.Status.Conditions {
|
||||||
if crd.Status.Conditions[i].Type == conditionType {
|
if crd.Status.Conditions[i].Type == conditionType {
|
||||||
return &crd.Status.Conditions[i]
|
return &crd.Status.Conditions[i]
|
||||||
@ -1742,10 +1715,6 @@ func float64Ptr(f float64) *float64 {
|
|||||||
return &f
|
return &f
|
||||||
}
|
}
|
||||||
|
|
||||||
func int64Ptr(f int64) *int64 {
|
|
||||||
return &f
|
|
||||||
}
|
|
||||||
|
|
||||||
func strPtr(str string) *string {
|
func strPtr(str string) *string {
|
||||||
return &str
|
return &str
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
@ -40,13 +40,13 @@ func TestInternalVersionIsHandlerVersion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1.NamespaceScoped)
|
||||||
|
|
||||||
assert.Equal(t, "v1beta1", noxuDefinition.Spec.Versions[0].Name)
|
assert.Equal(t, "v1beta1", noxuDefinition.Spec.Versions[0].Name)
|
||||||
assert.Equal(t, "v1beta2", noxuDefinition.Spec.Versions[1].Name)
|
assert.Equal(t, "v1beta2", noxuDefinition.Spec.Versions[1].Name)
|
||||||
assert.True(t, noxuDefinition.Spec.Versions[1].Storage)
|
assert.True(t, noxuDefinition.Spec.Versions[1].Storage)
|
||||||
|
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -64,16 +64,20 @@ func TestInternalVersionIsHandlerVersion(t *testing.T) {
|
|||||||
|
|
||||||
// update validation via update because the cache priming in CreateNewCustomResourceDefinition will fail otherwise
|
// update validation via update because the cache priming in CreateNewCustomResourceDefinition will fail otherwise
|
||||||
t.Logf("Updating CRD to validate apiVersion")
|
t.Logf("Updating CRD to validate apiVersion")
|
||||||
noxuDefinition, err = UpdateCustomResourceDefinitionWithRetry(apiExtensionClient, noxuDefinition.Name, func(crd *apiextensionsv1beta1.CustomResourceDefinition) {
|
noxuDefinition, err = UpdateCustomResourceDefinitionWithRetry(apiExtensionClient, noxuDefinition.Name, func(crd *apiextensionsv1.CustomResourceDefinition) {
|
||||||
crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{
|
for i := range crd.Spec.Versions {
|
||||||
OpenAPIV3Schema: &apiextensionsv1beta1.JSONSchemaProps{
|
crd.Spec.Versions[i].Schema = &apiextensionsv1.CustomResourceValidation{
|
||||||
Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
|
OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{
|
||||||
"apiVersion": {
|
Type: "object",
|
||||||
Pattern: "^mygroup.example.com/v1beta1$", // this means we can only patch via the v1beta1 handler version
|
Properties: map[string]apiextensionsv1.JSONSchemaProps{
|
||||||
|
"apiVersion": {
|
||||||
|
Pattern: "^mygroup.example.com/v1beta1$", // this means we can only patch via the v1beta1 handler version
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
Required: []string{"apiVersion"},
|
||||||
},
|
},
|
||||||
Required: []string{"apiVersion"},
|
}
|
||||||
},
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -134,8 +138,8 @@ func TestVersionedNamespacedScopedCRD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1.NamespaceScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -151,8 +155,8 @@ func TestVersionedClusterScopedCRD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.ClusterScoped)
|
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1.ClusterScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -162,40 +166,44 @@ func TestVersionedClusterScopedCRD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestStoragedVersionInNamespacedCRDStatus(t *testing.T) {
|
func TestStoragedVersionInNamespacedCRDStatus(t *testing.T) {
|
||||||
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.NamespaceScoped)
|
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1.NamespaceScoped)
|
||||||
ns := "not-the-default"
|
ns := "not-the-default"
|
||||||
testStoragedVersionInCRDStatus(t, ns, noxuDefinition)
|
testStoragedVersionInCRDStatus(t, ns, noxuDefinition)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStoragedVersionInClusterScopedCRDStatus(t *testing.T) {
|
func TestStoragedVersionInClusterScopedCRDStatus(t *testing.T) {
|
||||||
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.ClusterScoped)
|
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1.ClusterScoped)
|
||||||
ns := ""
|
ns := ""
|
||||||
testStoragedVersionInCRDStatus(t, ns, noxuDefinition)
|
testStoragedVersionInCRDStatus(t, ns, noxuDefinition)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testStoragedVersionInCRDStatus(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition) {
|
func testStoragedVersionInCRDStatus(t *testing.T, ns string, noxuDefinition *apiextensionsv1.CustomResourceDefinition) {
|
||||||
versionsV1Beta1Storage := []apiextensionsv1beta1.CustomResourceDefinitionVersion{
|
versionsV1Beta1Storage := []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||||
{
|
{
|
||||||
Name: "v1beta1",
|
Name: "v1beta1",
|
||||||
Served: true,
|
Served: true,
|
||||||
Storage: true,
|
Storage: true,
|
||||||
|
Schema: fixtures.AllowAllSchema(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "v1beta2",
|
Name: "v1beta2",
|
||||||
Served: true,
|
Served: true,
|
||||||
Storage: false,
|
Storage: false,
|
||||||
|
Schema: fixtures.AllowAllSchema(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
versionsV1Beta2Storage := []apiextensionsv1beta1.CustomResourceDefinitionVersion{
|
versionsV1Beta2Storage := []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||||
{
|
{
|
||||||
Name: "v1beta1",
|
Name: "v1beta1",
|
||||||
Served: true,
|
Served: true,
|
||||||
Storage: false,
|
Storage: false,
|
||||||
|
Schema: fixtures.AllowAllSchema(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "v1beta2",
|
Name: "v1beta2",
|
||||||
Served: true,
|
Served: true,
|
||||||
Storage: true,
|
Storage: true,
|
||||||
|
Schema: fixtures.AllowAllSchema(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t)
|
tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t)
|
||||||
@ -205,13 +213,13 @@ func testStoragedVersionInCRDStatus(t *testing.T, ns string, noxuDefinition *api
|
|||||||
defer tearDown()
|
defer tearDown()
|
||||||
|
|
||||||
noxuDefinition.Spec.Versions = versionsV1Beta1Storage
|
noxuDefinition.Spec.Versions = versionsV1Beta1Storage
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The storage version list should be initilized to storage version
|
// The storage version list should be initilized to storage version
|
||||||
crd, err := apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{})
|
crd, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -221,11 +229,11 @@ func testStoragedVersionInCRDStatus(t *testing.T, ns string, noxuDefinition *api
|
|||||||
|
|
||||||
// Changing CRD storage version should be reflected immediately
|
// Changing CRD storage version should be reflected immediately
|
||||||
crd.Spec.Versions = versionsV1Beta2Storage
|
crd.Spec.Versions = versionsV1Beta2Storage
|
||||||
_, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{})
|
_, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
crd, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{})
|
crd, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxuDefinition.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -233,7 +241,7 @@ func testStoragedVersionInCRDStatus(t *testing.T, ns string, noxuDefinition *api
|
|||||||
t.Errorf("expected %v, got %v", e, a)
|
t.Errorf("expected %v, got %v", e, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = fixtures.DeleteCustomResourceDefinition(crd, apiExtensionClient)
|
err = fixtures.DeleteV1CustomResourceDefinition(crd, apiExtensionClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/client-go/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
|
|
||||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
)
|
)
|
||||||
@ -51,15 +51,15 @@ func TestYAML(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
kind := noxuDefinition.Spec.Names.Kind
|
kind := noxuDefinition.Spec.Names.Kind
|
||||||
listKind := noxuDefinition.Spec.Names.ListKind
|
listKind := noxuDefinition.Spec.Names.ListKind
|
||||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Version
|
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name
|
||||||
|
|
||||||
rest := apiExtensionClient.Discovery().RESTClient()
|
rest := apiExtensionClient.Discovery().RESTClient()
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ func TestYAML(t *testing.T) {
|
|||||||
{
|
{
|
||||||
result, err := rest.Get().
|
result, err := rest.Get().
|
||||||
SetHeader("Accept", "application/yaml").
|
SetHeader("Accept", "application/yaml").
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name).
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err, string(result))
|
t.Fatal(err, string(result))
|
||||||
@ -88,7 +88,7 @@ func TestYAML(t *testing.T) {
|
|||||||
{
|
{
|
||||||
result, err := rest.Get().
|
result, err := rest.Get().
|
||||||
SetHeader("Accept", "application/yaml").
|
SetHeader("Accept", "application/yaml").
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "missingname").
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "missingname").
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
if !errors.IsNotFound(err) {
|
if !errors.IsNotFound(err) {
|
||||||
t.Fatalf("expected not found, got %v", err)
|
t.Fatalf("expected not found, got %v", err)
|
||||||
@ -123,7 +123,7 @@ values:
|
|||||||
result, err := rest.Post().
|
result, err := rest.Post().
|
||||||
SetHeader("Accept", "application/yaml").
|
SetHeader("Accept", "application/yaml").
|
||||||
SetHeader("Content-Type", "application/yaml").
|
SetHeader("Content-Type", "application/yaml").
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Body(yamlBody).
|
Body(yamlBody).
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -159,7 +159,7 @@ values:
|
|||||||
{
|
{
|
||||||
result, err := rest.Get().
|
result, err := rest.Get().
|
||||||
SetHeader("Accept", "application/yaml").
|
SetHeader("Accept", "application/yaml").
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "mytest").
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "mytest").
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -192,7 +192,7 @@ values:
|
|||||||
{
|
{
|
||||||
result, err := rest.Get().
|
result, err := rest.Get().
|
||||||
SetHeader("Accept", "application/yaml").
|
SetHeader("Accept", "application/yaml").
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err, string(result))
|
t.Fatal(err, string(result))
|
||||||
@ -236,7 +236,7 @@ values:
|
|||||||
{
|
{
|
||||||
result, err := rest.Get().
|
result, err := rest.Get().
|
||||||
SetHeader("Accept", "application/yaml").
|
SetHeader("Accept", "application/yaml").
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Param("watch", "true").
|
Param("watch", "true").
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
if !errors.IsNotAcceptable(err) {
|
if !errors.IsNotAcceptable(err) {
|
||||||
@ -273,7 +273,7 @@ values:
|
|||||||
result, err := rest.Put().
|
result, err := rest.Put().
|
||||||
SetHeader("Accept", "application/yaml").
|
SetHeader("Accept", "application/yaml").
|
||||||
SetHeader("Content-Type", "application/yaml").
|
SetHeader("Content-Type", "application/yaml").
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "mytest").
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "mytest").
|
||||||
Body(yamlBody).
|
Body(yamlBody).
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -314,7 +314,7 @@ values:
|
|||||||
result, err := rest.Patch(types.MergePatchType).
|
result, err := rest.Patch(types.MergePatchType).
|
||||||
SetHeader("Accept", "application/yaml").
|
SetHeader("Accept", "application/yaml").
|
||||||
SetHeader("Content-Type", "application/yaml").
|
SetHeader("Content-Type", "application/yaml").
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "mytest").
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "mytest").
|
||||||
Body(yamlBody).
|
Body(yamlBody).
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
if !errors.IsUnsupportedMediaType(err) {
|
if !errors.IsUnsupportedMediaType(err) {
|
||||||
@ -336,7 +336,7 @@ values:
|
|||||||
{
|
{
|
||||||
result, err := rest.Delete().
|
result, err := rest.Delete().
|
||||||
SetHeader("Accept", "application/yaml").
|
SetHeader("Accept", "application/yaml").
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "mytest").
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "mytest").
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err, string(result))
|
t.Fatal(err, string(result))
|
||||||
@ -370,14 +370,14 @@ func TestYAMLSubresource(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
noxuDefinition := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.ClusterScoped)[0]
|
noxuDefinition := NewNoxuSubresourcesCRDs(apiextensionsv1.ClusterScoped)[0]
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
kind := noxuDefinition.Spec.Names.Kind
|
kind := noxuDefinition.Spec.Names.Kind
|
||||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Version
|
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name
|
||||||
|
|
||||||
rest := apiExtensionClient.Discovery().RESTClient()
|
rest := apiExtensionClient.Discovery().RESTClient()
|
||||||
|
|
||||||
@ -397,7 +397,7 @@ spec:
|
|||||||
result, err := rest.Post().
|
result, err := rest.Post().
|
||||||
SetHeader("Accept", "application/yaml").
|
SetHeader("Accept", "application/yaml").
|
||||||
SetHeader("Content-Type", "application/yaml").
|
SetHeader("Content-Type", "application/yaml").
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Body(yamlBody).
|
Body(yamlBody).
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -427,7 +427,7 @@ spec:
|
|||||||
{
|
{
|
||||||
result, err := rest.Get().
|
result, err := rest.Get().
|
||||||
SetHeader("Accept", "application/yaml").
|
SetHeader("Accept", "application/yaml").
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "mytest", "status").
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "mytest", "status").
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -466,7 +466,7 @@ status:
|
|||||||
result, err := rest.Put().
|
result, err := rest.Put().
|
||||||
SetHeader("Accept", "application/yaml").
|
SetHeader("Accept", "application/yaml").
|
||||||
SetHeader("Content-Type", "application/yaml").
|
SetHeader("Content-Type", "application/yaml").
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "mytest", "status").
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "mytest", "status").
|
||||||
Body(yamlBody).
|
Body(yamlBody).
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -500,7 +500,7 @@ status:
|
|||||||
{
|
{
|
||||||
result, err := rest.Get().
|
result, err := rest.Get().
|
||||||
SetHeader("Accept", "application/yaml").
|
SetHeader("Accept", "application/yaml").
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural, "mytest", "scale").
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural, "mytest", "scale").
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -34,7 +34,7 @@ import (
|
|||||||
|
|
||||||
apps "k8s.io/api/apps/v1"
|
apps "k8s.io/api/apps/v1"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
@ -798,28 +798,35 @@ func TestMetadataClient(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fooCRD := &apiextensionsv1beta1.CustomResourceDefinition{
|
fooCRD := &apiextensionsv1.CustomResourceDefinition{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "foos.cr.bar.com",
|
Name: "foos.cr.bar.com",
|
||||||
},
|
},
|
||||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||||
Group: "cr.bar.com",
|
Group: "cr.bar.com",
|
||||||
Version: "v1",
|
Scope: apiextensionsv1.NamespaceScoped,
|
||||||
Scope: apiextensionsv1beta1.NamespaceScoped,
|
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
|
||||||
Plural: "foos",
|
Plural: "foos",
|
||||||
Kind: "Foo",
|
Kind: "Foo",
|
||||||
},
|
},
|
||||||
Subresources: &apiextensionsv1beta1.CustomResourceSubresources{
|
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||||
Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{},
|
{
|
||||||
|
Name: "v1",
|
||||||
|
Served: true,
|
||||||
|
Storage: true,
|
||||||
|
Schema: fixtures.AllowAllSchema(),
|
||||||
|
Subresources: &apiextensionsv1.CustomResourceSubresources{
|
||||||
|
Status: &apiextensionsv1.CustomResourceSubresourceStatus{},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fooCRD, err = fixtures.CreateNewCustomResourceDefinition(fooCRD, apiExtensionClient, dynamicClient)
|
fooCRD, err = fixtures.CreateNewV1CustomResourceDefinition(fooCRD, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
crdGVR := schema.GroupVersionResource{Group: fooCRD.Spec.Group, Version: fooCRD.Spec.Version, Resource: "foos"}
|
crdGVR := schema.GroupVersionResource{Group: fooCRD.Spec.Group, Version: fooCRD.Spec.Versions[0].Name, Resource: "foos"}
|
||||||
|
|
||||||
testcases := []struct {
|
testcases := []struct {
|
||||||
name string
|
name string
|
||||||
@ -1119,26 +1126,33 @@ func TestAPICRDProtobuf(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fooCRD := &apiextensionsv1beta1.CustomResourceDefinition{
|
fooCRD := &apiextensionsv1.CustomResourceDefinition{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "foos.cr.bar.com",
|
Name: "foos.cr.bar.com",
|
||||||
},
|
},
|
||||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||||
Group: "cr.bar.com",
|
Group: "cr.bar.com",
|
||||||
Version: "v1",
|
Scope: apiextensionsv1.NamespaceScoped,
|
||||||
Scope: apiextensionsv1beta1.NamespaceScoped,
|
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
|
||||||
Plural: "foos",
|
Plural: "foos",
|
||||||
Kind: "Foo",
|
Kind: "Foo",
|
||||||
},
|
},
|
||||||
Subresources: &apiextensionsv1beta1.CustomResourceSubresources{Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{}},
|
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||||
|
{
|
||||||
|
Name: "v1",
|
||||||
|
Served: true,
|
||||||
|
Storage: true,
|
||||||
|
Schema: fixtures.AllowAllSchema(),
|
||||||
|
Subresources: &apiextensionsv1.CustomResourceSubresources{Status: &apiextensionsv1.CustomResourceSubresourceStatus{}},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fooCRD, err = fixtures.CreateNewCustomResourceDefinition(fooCRD, apiExtensionClient, dynamicClient)
|
fooCRD, err = fixtures.CreateNewV1CustomResourceDefinition(fooCRD, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
crdGVR := schema.GroupVersionResource{Group: fooCRD.Spec.Group, Version: fooCRD.Spec.Version, Resource: "foos"}
|
crdGVR := schema.GroupVersionResource{Group: fooCRD.Spec.Group, Version: fooCRD.Spec.Versions[0].Name, Resource: "foos"}
|
||||||
crclient := dynamicClient.Resource(crdGVR).Namespace(testNamespace)
|
crclient := dynamicClient.Resource(crdGVR).Namespace(testNamespace)
|
||||||
|
|
||||||
testcases := []struct {
|
testcases := []struct {
|
||||||
@ -1331,25 +1345,32 @@ func TestTransform(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fooCRD := &apiextensionsv1beta1.CustomResourceDefinition{
|
fooCRD := &apiextensionsv1.CustomResourceDefinition{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "foos.cr.bar.com",
|
Name: "foos.cr.bar.com",
|
||||||
},
|
},
|
||||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||||
Group: "cr.bar.com",
|
Group: "cr.bar.com",
|
||||||
Version: "v1",
|
Scope: apiextensionsv1.NamespaceScoped,
|
||||||
Scope: apiextensionsv1beta1.NamespaceScoped,
|
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
|
||||||
Plural: "foos",
|
Plural: "foos",
|
||||||
Kind: "Foo",
|
Kind: "Foo",
|
||||||
},
|
},
|
||||||
|
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||||
|
{
|
||||||
|
Name: "v1",
|
||||||
|
Served: true,
|
||||||
|
Storage: true,
|
||||||
|
Schema: fixtures.AllowAllSchema(),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fooCRD, err = fixtures.CreateNewCustomResourceDefinition(fooCRD, apiExtensionClient, dynamicClient)
|
fooCRD, err = fixtures.CreateNewV1CustomResourceDefinition(fooCRD, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
crdGVR := schema.GroupVersionResource{Group: fooCRD.Spec.Group, Version: fooCRD.Spec.Version, Resource: "foos"}
|
crdGVR := schema.GroupVersionResource{Group: fooCRD.Spec.Group, Version: fooCRD.Spec.Versions[0].Name, Resource: "foos"}
|
||||||
crclient := dynamicClient.Resource(crdGVR).Namespace(testNamespace)
|
crclient := dynamicClient.Resource(crdGVR).Namespace(testNamespace)
|
||||||
|
|
||||||
testcases := []struct {
|
testcases := []struct {
|
||||||
|
234
test/integration/apiserver/apply/apply_crd_beta_test.go
Normal file
234
test/integration/apiserver/apply/apply_crd_beta_test.go
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2021 The Kubernetes 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 apiserver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||||
|
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
|
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
genericfeatures "k8s.io/apiserver/pkg/features"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
|
apiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
|
||||||
|
"k8s.io/kubernetes/test/integration/framework"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestApplyCRDNoSchema tests that CRDs and CRs can both be applied to with a PATCH request with the apply content type
|
||||||
|
// when there is no validation field provided.
|
||||||
|
func TestApplyCRDNoSchema(t *testing.T) {
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.ServerSideApply, true)()
|
||||||
|
|
||||||
|
server, err := apiservertesting.StartTestServer(t, apiservertesting.NewDefaultTestServerOptions(), nil, framework.SharedEtcd())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer server.TearDownFn()
|
||||||
|
config := server.ClientConfig
|
||||||
|
|
||||||
|
apiExtensionClient, err := clientset.NewForConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
dynamicClient, err := dynamic.NewForConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
noxuDefinition := nearlyRemovedBetaMultipleVersionNoxuCRD(apiextensionsv1beta1.ClusterScoped)
|
||||||
|
|
||||||
|
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
kind := noxuDefinition.Spec.Names.Kind
|
||||||
|
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Version
|
||||||
|
name := "mytest"
|
||||||
|
|
||||||
|
rest := apiExtensionClient.Discovery().RESTClient()
|
||||||
|
yamlBody := []byte(fmt.Sprintf(`
|
||||||
|
apiVersion: %s
|
||||||
|
kind: %s
|
||||||
|
metadata:
|
||||||
|
name: %s
|
||||||
|
spec:
|
||||||
|
replicas: 1`, apiVersion, kind, name))
|
||||||
|
result, err := rest.Patch(types.ApplyPatchType).
|
||||||
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
||||||
|
Name(name).
|
||||||
|
Param("fieldManager", "apply_test").
|
||||||
|
Body(yamlBody).
|
||||||
|
DoRaw(context.TODO())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create custom resource with apply: %v:\n%v", err, string(result))
|
||||||
|
}
|
||||||
|
verifyReplicas(t, result, 1)
|
||||||
|
|
||||||
|
// Patch object to change the number of replicas
|
||||||
|
result, err = rest.Patch(types.MergePatchType).
|
||||||
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
||||||
|
Name(name).
|
||||||
|
Body([]byte(`{"spec":{"replicas": 5}}`)).
|
||||||
|
DoRaw(context.TODO())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to update number of replicas with merge patch: %v:\n%v", err, string(result))
|
||||||
|
}
|
||||||
|
verifyReplicas(t, result, 5)
|
||||||
|
|
||||||
|
// Re-apply, we should get conflicts now, since the number of replicas was changed.
|
||||||
|
result, err = rest.Patch(types.ApplyPatchType).
|
||||||
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
||||||
|
Name(name).
|
||||||
|
Param("fieldManager", "apply_test").
|
||||||
|
Body(yamlBody).
|
||||||
|
DoRaw(context.TODO())
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("Expecting to get conflicts when applying object after updating replicas, got no error: %s", result)
|
||||||
|
}
|
||||||
|
status, ok := err.(*apierrors.StatusError)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("Expecting to get conflicts as API error")
|
||||||
|
}
|
||||||
|
if len(status.Status().Details.Causes) != 1 {
|
||||||
|
t.Fatalf("Expecting to get one conflict when applying object after updating replicas, got: %v", status.Status().Details.Causes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-apply with force, should work fine.
|
||||||
|
result, err = rest.Patch(types.ApplyPatchType).
|
||||||
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
||||||
|
Name(name).
|
||||||
|
Param("force", "true").
|
||||||
|
Param("fieldManager", "apply_test").
|
||||||
|
Body(yamlBody).
|
||||||
|
DoRaw(context.TODO())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to apply object with force after updating replicas: %v:\n%v", err, string(result))
|
||||||
|
}
|
||||||
|
verifyReplicas(t, result, 1)
|
||||||
|
|
||||||
|
// Try to set managed fields using a subresource and verify that it has no effect
|
||||||
|
existingManagedFields, err := getManagedFields(result)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to get managedFields from response: %v", err)
|
||||||
|
}
|
||||||
|
updateBytes := []byte(`{
|
||||||
|
"metadata": {
|
||||||
|
"managedFields": [{
|
||||||
|
"manager":"testing",
|
||||||
|
"operation":"Update",
|
||||||
|
"apiVersion":"v1",
|
||||||
|
"fieldsType":"FieldsV1",
|
||||||
|
"fieldsV1":{
|
||||||
|
"f:spec":{
|
||||||
|
"f:containers":{
|
||||||
|
"k:{\"name\":\"testing\"}":{
|
||||||
|
".":{},
|
||||||
|
"f:image":{},
|
||||||
|
"f:name":{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
result, err = rest.Patch(types.MergePatchType).
|
||||||
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
||||||
|
SubResource("status").
|
||||||
|
Name(name).
|
||||||
|
Param("fieldManager", "subresource_test").
|
||||||
|
Body(updateBytes).
|
||||||
|
DoRaw(context.TODO())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error updating subresource: %v ", err)
|
||||||
|
}
|
||||||
|
newManagedFields, err := getManagedFields(result)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to get managedFields from response: %v", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(existingManagedFields, newManagedFields) {
|
||||||
|
t.Fatalf("Expected managed fields to not have changed when trying manually settting them via subresoures.\n\nExpected: %#v\n\nGot: %#v", existingManagedFields, newManagedFields)
|
||||||
|
}
|
||||||
|
|
||||||
|
// However, it is possible to modify managed fields using the main resource
|
||||||
|
result, err = rest.Patch(types.MergePatchType).
|
||||||
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
||||||
|
Name(name).
|
||||||
|
Param("fieldManager", "subresource_test").
|
||||||
|
Body([]byte(`{"metadata":{"managedFields":[{}]}}`)).
|
||||||
|
DoRaw(context.TODO())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error updating managed fields of the main resource: %v ", err)
|
||||||
|
}
|
||||||
|
newManagedFields, err = getManagedFields(result)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to get managedFields from response: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(newManagedFields) != 0 {
|
||||||
|
t.Fatalf("Expected managed fields to have been reset, but got: %v", newManagedFields)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func nearlyRemovedBetaMultipleVersionNoxuCRD(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition {
|
||||||
|
return &apiextensionsv1beta1.CustomResourceDefinition{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"},
|
||||||
|
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||||
|
Group: "mygroup.example.com",
|
||||||
|
Version: "v1beta1",
|
||||||
|
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||||
|
Plural: "noxus",
|
||||||
|
Singular: "nonenglishnoxu",
|
||||||
|
Kind: "WishIHadChosenNoxu",
|
||||||
|
ShortNames: []string{"foo", "bar", "abc", "def"},
|
||||||
|
ListKind: "NoxuItemList",
|
||||||
|
Categories: []string{"all"},
|
||||||
|
},
|
||||||
|
Scope: scope,
|
||||||
|
Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{
|
||||||
|
{
|
||||||
|
Name: "v1beta1",
|
||||||
|
Served: true,
|
||||||
|
Storage: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "v1beta2",
|
||||||
|
Served: true,
|
||||||
|
Storage: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "v0",
|
||||||
|
Served: false,
|
||||||
|
Storage: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Subresources: &apiextensionsv1beta1.CustomResourceSubresources{
|
||||||
|
Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
@ -20,8 +20,18 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
|
|
||||||
|
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||||
|
|
||||||
|
"go.etcd.io/etcd/clientv3"
|
||||||
|
"go.etcd.io/etcd/pkg/transport"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
|
||||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||||
@ -39,163 +49,6 @@ import (
|
|||||||
"k8s.io/kubernetes/test/integration/framework"
|
"k8s.io/kubernetes/test/integration/framework"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestApplyCRDNoSchema tests that CRDs and CRs can both be applied to with a PATCH request with the apply content type
|
|
||||||
// when there is no validation field provided.
|
|
||||||
func TestApplyCRDNoSchema(t *testing.T) {
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.ServerSideApply, true)()
|
|
||||||
|
|
||||||
server, err := apiservertesting.StartTestServer(t, apiservertesting.NewDefaultTestServerOptions(), nil, framework.SharedEtcd())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer server.TearDownFn()
|
|
||||||
config := server.ClientConfig
|
|
||||||
|
|
||||||
apiExtensionClient, err := clientset.NewForConfig(config)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
dynamicClient, err := dynamic.NewForConfig(config)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.ClusterScoped)
|
|
||||||
|
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
kind := noxuDefinition.Spec.Names.Kind
|
|
||||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Version
|
|
||||||
name := "mytest"
|
|
||||||
|
|
||||||
rest := apiExtensionClient.Discovery().RESTClient()
|
|
||||||
yamlBody := []byte(fmt.Sprintf(`
|
|
||||||
apiVersion: %s
|
|
||||||
kind: %s
|
|
||||||
metadata:
|
|
||||||
name: %s
|
|
||||||
spec:
|
|
||||||
replicas: 1`, apiVersion, kind, name))
|
|
||||||
result, err := rest.Patch(types.ApplyPatchType).
|
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
|
||||||
Name(name).
|
|
||||||
Param("fieldManager", "apply_test").
|
|
||||||
Body(yamlBody).
|
|
||||||
DoRaw(context.TODO())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to create custom resource with apply: %v:\n%v", err, string(result))
|
|
||||||
}
|
|
||||||
verifyReplicas(t, result, 1)
|
|
||||||
|
|
||||||
// Patch object to change the number of replicas
|
|
||||||
result, err = rest.Patch(types.MergePatchType).
|
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
|
||||||
Name(name).
|
|
||||||
Body([]byte(`{"spec":{"replicas": 5}}`)).
|
|
||||||
DoRaw(context.TODO())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to update number of replicas with merge patch: %v:\n%v", err, string(result))
|
|
||||||
}
|
|
||||||
verifyReplicas(t, result, 5)
|
|
||||||
|
|
||||||
// Re-apply, we should get conflicts now, since the number of replicas was changed.
|
|
||||||
result, err = rest.Patch(types.ApplyPatchType).
|
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
|
||||||
Name(name).
|
|
||||||
Param("fieldManager", "apply_test").
|
|
||||||
Body(yamlBody).
|
|
||||||
DoRaw(context.TODO())
|
|
||||||
if err == nil {
|
|
||||||
t.Fatalf("Expecting to get conflicts when applying object after updating replicas, got no error: %s", result)
|
|
||||||
}
|
|
||||||
status, ok := err.(*apierrors.StatusError)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("Expecting to get conflicts as API error")
|
|
||||||
}
|
|
||||||
if len(status.Status().Details.Causes) != 1 {
|
|
||||||
t.Fatalf("Expecting to get one conflict when applying object after updating replicas, got: %v", status.Status().Details.Causes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-apply with force, should work fine.
|
|
||||||
result, err = rest.Patch(types.ApplyPatchType).
|
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
|
||||||
Name(name).
|
|
||||||
Param("force", "true").
|
|
||||||
Param("fieldManager", "apply_test").
|
|
||||||
Body(yamlBody).
|
|
||||||
DoRaw(context.TODO())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to apply object with force after updating replicas: %v:\n%v", err, string(result))
|
|
||||||
}
|
|
||||||
verifyReplicas(t, result, 1)
|
|
||||||
|
|
||||||
// Try to set managed fields using a subresource and verify that it has no effect
|
|
||||||
existingManagedFields, err := getManagedFields(result)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to get managedFields from response: %v", err)
|
|
||||||
}
|
|
||||||
updateBytes := []byte(`{
|
|
||||||
"metadata": {
|
|
||||||
"managedFields": [{
|
|
||||||
"manager":"testing",
|
|
||||||
"operation":"Update",
|
|
||||||
"apiVersion":"v1",
|
|
||||||
"fieldsType":"FieldsV1",
|
|
||||||
"fieldsV1":{
|
|
||||||
"f:spec":{
|
|
||||||
"f:containers":{
|
|
||||||
"k:{\"name\":\"testing\"}":{
|
|
||||||
".":{},
|
|
||||||
"f:image":{},
|
|
||||||
"f:name":{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
}`)
|
|
||||||
result, err = rest.Patch(types.MergePatchType).
|
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
|
||||||
SubResource("status").
|
|
||||||
Name(name).
|
|
||||||
Param("fieldManager", "subresource_test").
|
|
||||||
Body(updateBytes).
|
|
||||||
DoRaw(context.TODO())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error updating subresource: %v ", err)
|
|
||||||
}
|
|
||||||
newManagedFields, err := getManagedFields(result)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to get managedFields from response: %v", err)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(existingManagedFields, newManagedFields) {
|
|
||||||
t.Fatalf("Expected managed fields to not have changed when trying manually settting them via subresoures.\n\nExpected: %#v\n\nGot: %#v", existingManagedFields, newManagedFields)
|
|
||||||
}
|
|
||||||
|
|
||||||
// However, it is possible to modify managed fields using the main resource
|
|
||||||
result, err = rest.Patch(types.MergePatchType).
|
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
|
||||||
Name(name).
|
|
||||||
Param("fieldManager", "subresource_test").
|
|
||||||
Body([]byte(`{"metadata":{"managedFields":[{}]}}`)).
|
|
||||||
DoRaw(context.TODO())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error updating managed fields of the main resource: %v ", err)
|
|
||||||
}
|
|
||||||
newManagedFields, err = getManagedFields(result)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to get managedFields from response: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(newManagedFields) != 0 {
|
|
||||||
t.Fatalf("Expected managed fields to have been reset, but got: %v", newManagedFields)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestApplyCRDStructuralSchema tests that when a CRD has a structural schema in its validation field,
|
// TestApplyCRDStructuralSchema tests that when a CRD has a structural schema in its validation field,
|
||||||
// it will be used to construct the CR schema used by apply.
|
// it will be used to construct the CR schema used by apply.
|
||||||
func TestApplyCRDStructuralSchema(t *testing.T) {
|
func TestApplyCRDStructuralSchema(t *testing.T) {
|
||||||
@ -217,9 +70,9 @@ func TestApplyCRDStructuralSchema(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.ClusterScoped)
|
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1.ClusterScoped)
|
||||||
|
|
||||||
var c apiextensionsv1beta1.CustomResourceValidation
|
var c apiextensionsv1.CustomResourceValidation
|
||||||
err = json.Unmarshal([]byte(`{
|
err = json.Unmarshal([]byte(`{
|
||||||
"openAPIV3Schema": {
|
"openAPIV3Schema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -274,17 +127,17 @@ func TestApplyCRDStructuralSchema(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
noxuDefinition.Spec.Validation = &c
|
for i := range noxuDefinition.Spec.Versions {
|
||||||
falseBool := false
|
noxuDefinition.Spec.Versions[i].Schema = &c
|
||||||
noxuDefinition.Spec.PreserveUnknownFields = &falseBool
|
}
|
||||||
|
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
kind := noxuDefinition.Spec.Names.Kind
|
kind := noxuDefinition.Spec.Names.Kind
|
||||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Version
|
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name
|
||||||
name := "mytest"
|
name := "mytest"
|
||||||
|
|
||||||
rest := apiExtensionClient.Discovery().RESTClient()
|
rest := apiExtensionClient.Discovery().RESTClient()
|
||||||
@ -303,7 +156,7 @@ spec:
|
|||||||
containerPort: 80
|
containerPort: 80
|
||||||
protocol: TCP`, apiVersion, kind, name))
|
protocol: TCP`, apiVersion, kind, name))
|
||||||
result, err := rest.Patch(types.ApplyPatchType).
|
result, err := rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Name(name).
|
Name(name).
|
||||||
Param("fieldManager", "apply_test").
|
Param("fieldManager", "apply_test").
|
||||||
Body(yamlBody).
|
Body(yamlBody).
|
||||||
@ -318,7 +171,7 @@ spec:
|
|||||||
|
|
||||||
// Patch object to add another finalizer to the finalizers list
|
// Patch object to add another finalizer to the finalizers list
|
||||||
result, err = rest.Patch(types.MergePatchType).
|
result, err = rest.Patch(types.MergePatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Name(name).
|
Name(name).
|
||||||
Body([]byte(`{"metadata":{"finalizers":["test-finalizer","another-one"]}}`)).
|
Body([]byte(`{"metadata":{"finalizers":["test-finalizer","another-one"]}}`)).
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
@ -331,7 +184,7 @@ spec:
|
|||||||
|
|
||||||
// Re-apply the same config, should work fine, since finalizers should have the list-type extension 'set'.
|
// Re-apply the same config, should work fine, since finalizers should have the list-type extension 'set'.
|
||||||
result, err = rest.Patch(types.ApplyPatchType).
|
result, err = rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Name(name).
|
Name(name).
|
||||||
Param("fieldManager", "apply_test").
|
Param("fieldManager", "apply_test").
|
||||||
SetHeader("Accept", "application/json").
|
SetHeader("Accept", "application/json").
|
||||||
@ -346,7 +199,7 @@ spec:
|
|||||||
|
|
||||||
// Patch object to change the number of replicas
|
// Patch object to change the number of replicas
|
||||||
result, err = rest.Patch(types.MergePatchType).
|
result, err = rest.Patch(types.MergePatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Name(name).
|
Name(name).
|
||||||
Body([]byte(`{"spec":{"replicas": 5}}`)).
|
Body([]byte(`{"spec":{"replicas": 5}}`)).
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
@ -357,7 +210,7 @@ spec:
|
|||||||
|
|
||||||
// Re-apply, we should get conflicts now, since the number of replicas was changed.
|
// Re-apply, we should get conflicts now, since the number of replicas was changed.
|
||||||
result, err = rest.Patch(types.ApplyPatchType).
|
result, err = rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Name(name).
|
Name(name).
|
||||||
Param("fieldManager", "apply_test").
|
Param("fieldManager", "apply_test").
|
||||||
Body(yamlBody).
|
Body(yamlBody).
|
||||||
@ -375,7 +228,7 @@ spec:
|
|||||||
|
|
||||||
// Re-apply with force, should work fine.
|
// Re-apply with force, should work fine.
|
||||||
result, err = rest.Patch(types.ApplyPatchType).
|
result, err = rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Name(name).
|
Name(name).
|
||||||
Param("force", "true").
|
Param("force", "true").
|
||||||
Param("fieldManager", "apply_test").
|
Param("fieldManager", "apply_test").
|
||||||
@ -388,7 +241,7 @@ spec:
|
|||||||
|
|
||||||
// New applier tries to edit an existing list item, we should get conflicts.
|
// New applier tries to edit an existing list item, we should get conflicts.
|
||||||
result, err = rest.Patch(types.ApplyPatchType).
|
result, err = rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Name(name).
|
Name(name).
|
||||||
Param("fieldManager", "apply_test_2").
|
Param("fieldManager", "apply_test_2").
|
||||||
Body([]byte(fmt.Sprintf(`
|
Body([]byte(fmt.Sprintf(`
|
||||||
@ -415,7 +268,7 @@ spec:
|
|||||||
|
|
||||||
// New applier tries to add a new list item, should work fine.
|
// New applier tries to add a new list item, should work fine.
|
||||||
result, err = rest.Patch(types.ApplyPatchType).
|
result, err = rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Name(name).
|
Name(name).
|
||||||
Param("fieldManager", "apply_test_2").
|
Param("fieldManager", "apply_test_2").
|
||||||
Body([]byte(fmt.Sprintf(`
|
Body([]byte(fmt.Sprintf(`
|
||||||
@ -459,7 +312,7 @@ spec:
|
|||||||
"protocol": "TCP"
|
"protocol": "TCP"
|
||||||
}`, apiVersion, kind, "should-not-exist"))
|
}`, apiVersion, kind, "should-not-exist"))
|
||||||
_, err = rest.Put().
|
_, err = rest.Put().
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Name("should-not-exist").
|
Name("should-not-exist").
|
||||||
Param("fieldManager", "apply_test").
|
Param("fieldManager", "apply_test").
|
||||||
Body(notExistingYAMLBody).
|
Body(notExistingYAMLBody).
|
||||||
@ -552,12 +405,45 @@ func verifyNumPorts(t *testing.T, b []byte, n int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func findCRDCondition(crd *apiextensionsv1.CustomResourceDefinition, conditionType apiextensionsv1.CustomResourceDefinitionConditionType) *apiextensionsv1.CustomResourceDefinitionCondition {
|
||||||
|
for i := range crd.Status.Conditions {
|
||||||
|
if crd.Status.Conditions[i].Type == conditionType {
|
||||||
|
return &crd.Status.Conditions[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// TestApplyCRDUnhandledSchema tests that when a CRD has a schema that kube-openapi ToProtoModels cannot handle correctly,
|
// TestApplyCRDUnhandledSchema tests that when a CRD has a schema that kube-openapi ToProtoModels cannot handle correctly,
|
||||||
// apply falls back to non-schema behavior
|
// apply falls back to non-schema behavior
|
||||||
func TestApplyCRDUnhandledSchema(t *testing.T) {
|
func TestApplyCRDUnhandledSchema(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.ServerSideApply, true)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.ServerSideApply, true)()
|
||||||
|
|
||||||
server, err := apiservertesting.StartTestServer(t, apiservertesting.NewDefaultTestServerOptions(), nil, framework.SharedEtcd())
|
storageConfig := framework.SharedEtcd()
|
||||||
|
tlsInfo := transport.TLSInfo{
|
||||||
|
CertFile: storageConfig.Transport.CertFile,
|
||||||
|
KeyFile: storageConfig.Transport.KeyFile,
|
||||||
|
TrustedCAFile: storageConfig.Transport.TrustedCAFile,
|
||||||
|
}
|
||||||
|
tlsConfig, err := tlsInfo.ClientConfig()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
etcdConfig := clientv3.Config{
|
||||||
|
Endpoints: storageConfig.Transport.ServerList,
|
||||||
|
DialTimeout: 20 * time.Second,
|
||||||
|
DialOptions: []grpc.DialOption{
|
||||||
|
grpc.WithBlock(), // block until the underlying connection is up
|
||||||
|
},
|
||||||
|
TLS: tlsConfig,
|
||||||
|
}
|
||||||
|
etcdclient, err := clientv3.New(etcdConfig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
server, err := apiservertesting.StartTestServer(t, apiservertesting.NewDefaultTestServerOptions(), nil, storageConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -568,12 +454,33 @@ func TestApplyCRDUnhandledSchema(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
dynamicClient, err := dynamic.NewForConfig(config)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
// this has to be v1beta1, so we can have an item with validation that does not match. v1 validation prevents this.
|
||||||
|
|
||||||
|
noxuBetaDefinition := &apiextensionsv1beta1.CustomResourceDefinition{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
Kind: "CustomResourceDefinition",
|
||||||
|
APIVersion: "apiextensions.k8s.io/v1beta1",
|
||||||
|
},
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"},
|
||||||
|
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||||
|
Group: "mygroup.example.com",
|
||||||
|
Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{{
|
||||||
|
Name: "v1beta1",
|
||||||
|
Served: true,
|
||||||
|
Storage: true,
|
||||||
|
}},
|
||||||
|
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||||
|
Plural: "noxus",
|
||||||
|
Singular: "nonenglishnoxu",
|
||||||
|
Kind: "WishIHadChosenNoxu",
|
||||||
|
ShortNames: []string{"foo", "bar", "abc", "def"},
|
||||||
|
ListKind: "NoxuItemList",
|
||||||
|
Categories: []string{"all"},
|
||||||
|
},
|
||||||
|
Scope: apiextensionsv1beta1.ClusterScoped,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// This is a schema that kube-openapi ToProtoModels does not handle correctly.
|
// This is a schema that kube-openapi ToProtoModels does not handle correctly.
|
||||||
// https://github.com/kubernetes/kubernetes/blob/38752f7f99869ed65fb44378360a517649dc2f83/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go#L184
|
// https://github.com/kubernetes/kubernetes/blob/38752f7f99869ed65fb44378360a517649dc2f83/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go#L184
|
||||||
@ -590,15 +497,44 @@ func TestApplyCRDUnhandledSchema(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
noxuDefinition.Spec.Validation = &c
|
noxuBetaDefinition.Spec.Validation = &c
|
||||||
|
|
||||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
betaBytes, err := json.Marshal(noxuBetaDefinition)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(string(betaBytes))
|
||||||
|
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceNone)
|
||||||
|
key := path.Join("/", storageConfig.Prefix, "apiextensions.k8s.io", "customresourcedefinitions", noxuBetaDefinition.Name)
|
||||||
|
if _, err := etcdclient.Put(ctx, key, string(betaBytes)); err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
noxuDefinition, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxuBetaDefinition.Name, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// wait until the CRD is established
|
||||||
|
err = wait.Poll(100*time.Millisecond, 10*time.Second, func() (bool, error) {
|
||||||
|
localCrd, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), noxuBetaDefinition.Name, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
condition := findCRDCondition(localCrd, apiextensionsv1.Established)
|
||||||
|
if condition == nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
if condition.Status == apiextensionsv1.ConditionTrue {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
kind := noxuDefinition.Spec.Names.Kind
|
kind := noxuDefinition.Spec.Names.Kind
|
||||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Version
|
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name
|
||||||
name := "mytest"
|
name := "mytest"
|
||||||
|
|
||||||
rest := apiExtensionClient.Discovery().RESTClient()
|
rest := apiExtensionClient.Discovery().RESTClient()
|
||||||
@ -610,7 +546,7 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
replicas: 1`, apiVersion, kind, name))
|
replicas: 1`, apiVersion, kind, name))
|
||||||
result, err := rest.Patch(types.ApplyPatchType).
|
result, err := rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Name(name).
|
Name(name).
|
||||||
Param("fieldManager", "apply_test").
|
Param("fieldManager", "apply_test").
|
||||||
Body(yamlBody).
|
Body(yamlBody).
|
||||||
@ -622,7 +558,7 @@ spec:
|
|||||||
|
|
||||||
// Patch object to change the number of replicas
|
// Patch object to change the number of replicas
|
||||||
result, err = rest.Patch(types.MergePatchType).
|
result, err = rest.Patch(types.MergePatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Name(name).
|
Name(name).
|
||||||
Body([]byte(`{"spec":{"replicas": 5}}`)).
|
Body([]byte(`{"spec":{"replicas": 5}}`)).
|
||||||
DoRaw(context.TODO())
|
DoRaw(context.TODO())
|
||||||
@ -633,7 +569,7 @@ spec:
|
|||||||
|
|
||||||
// Re-apply, we should get conflicts now, since the number of replicas was changed.
|
// Re-apply, we should get conflicts now, since the number of replicas was changed.
|
||||||
result, err = rest.Patch(types.ApplyPatchType).
|
result, err = rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Name(name).
|
Name(name).
|
||||||
Param("fieldManager", "apply_test").
|
Param("fieldManager", "apply_test").
|
||||||
Body(yamlBody).
|
Body(yamlBody).
|
||||||
@ -651,7 +587,7 @@ spec:
|
|||||||
|
|
||||||
// Re-apply with force, should work fine.
|
// Re-apply with force, should work fine.
|
||||||
result, err = rest.Patch(types.ApplyPatchType).
|
result, err = rest.Patch(types.ApplyPatchType).
|
||||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Version, noxuDefinition.Spec.Names.Plural).
|
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||||
Name(name).
|
Name(name).
|
||||||
Param("force", "true").
|
Param("force", "true").
|
||||||
Param("fieldManager", "apply_test").
|
Param("fieldManager", "apply_test").
|
||||||
|
@ -26,7 +26,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
apiextensionstestserver "k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
apiextensionstestserver "k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
@ -136,11 +136,11 @@ func newOwnerRC(name, namespace string) *v1.ReplicationController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCRDInstance(definition *apiextensionsv1beta1.CustomResourceDefinition, namespace, name string) *unstructured.Unstructured {
|
func newCRDInstance(definition *apiextensionsv1.CustomResourceDefinition, namespace, name string) *unstructured.Unstructured {
|
||||||
return &unstructured.Unstructured{
|
return &unstructured.Unstructured{
|
||||||
Object: map[string]interface{}{
|
Object: map[string]interface{}{
|
||||||
"kind": definition.Spec.Names.Kind,
|
"kind": definition.Spec.Names.Kind,
|
||||||
"apiVersion": definition.Spec.Group + "/" + definition.Spec.Version,
|
"apiVersion": definition.Spec.Group + "/" + definition.Spec.Versions[0].Name,
|
||||||
"metadata": map[string]interface{}{
|
"metadata": map[string]interface{}{
|
||||||
"name": name,
|
"name": name,
|
||||||
"namespace": namespace,
|
"namespace": namespace,
|
||||||
@ -180,18 +180,18 @@ func createRandomCustomResourceDefinition(
|
|||||||
t *testing.T, apiExtensionClient apiextensionsclientset.Interface,
|
t *testing.T, apiExtensionClient apiextensionsclientset.Interface,
|
||||||
dynamicClient dynamic.Interface,
|
dynamicClient dynamic.Interface,
|
||||||
namespace string,
|
namespace string,
|
||||||
) (*apiextensionsv1beta1.CustomResourceDefinition, dynamic.ResourceInterface) {
|
) (*apiextensionsv1.CustomResourceDefinition, dynamic.ResourceInterface) {
|
||||||
// Create a random custom resource definition and ensure it's available for
|
// Create a random custom resource definition and ensure it's available for
|
||||||
// use.
|
// use.
|
||||||
definition := apiextensionstestserver.NewRandomNameCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
definition := apiextensionstestserver.NewRandomNameV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||||
|
|
||||||
definition, err := apiextensionstestserver.CreateNewCustomResourceDefinition(definition, apiExtensionClient, dynamicClient)
|
definition, err := apiextensionstestserver.CreateNewV1CustomResourceDefinition(definition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create CustomResourceDefinition: %v", err)
|
t.Fatalf("failed to create CustomResourceDefinition: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a client for the custom resource.
|
// Get a client for the custom resource.
|
||||||
gvr := schema.GroupVersionResource{Group: definition.Spec.Group, Version: definition.Spec.Version, Resource: definition.Spec.Names.Plural}
|
gvr := schema.GroupVersionResource{Group: definition.Spec.Group, Version: definition.Spec.Versions[0].Name, Resource: definition.Spec.Names.Plural}
|
||||||
|
|
||||||
resourceClient := dynamicClient.Resource(gvr).Namespace(namespace)
|
resourceClient := dynamicClient.Resource(gvr).Namespace(namespace)
|
||||||
|
|
||||||
@ -1230,14 +1230,14 @@ func TestCRDDeletionCascading(t *testing.T) {
|
|||||||
t.Logf("Second pass CRD cascading deletion")
|
t.Logf("Second pass CRD cascading deletion")
|
||||||
accessor := meta.NewAccessor()
|
accessor := meta.NewAccessor()
|
||||||
accessor.SetResourceVersion(definition, "")
|
accessor.SetResourceVersion(definition, "")
|
||||||
_, err := apiextensionstestserver.CreateNewCustomResourceDefinition(definition, apiExtensionClient, dynamicClient)
|
_, err := apiextensionstestserver.CreateNewV1CustomResourceDefinition(definition, apiExtensionClient, dynamicClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create CustomResourceDefinition: %v", err)
|
t.Fatalf("failed to create CustomResourceDefinition: %v", err)
|
||||||
}
|
}
|
||||||
testCRDDeletion(t, ctx, ns, definition, resourceClient)
|
testCRDDeletion(t, ctx, ns, definition, resourceClient)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testCRDDeletion(t *testing.T, ctx *testContext, ns *v1.Namespace, definition *apiextensionsv1beta1.CustomResourceDefinition, resourceClient dynamic.ResourceInterface) {
|
func testCRDDeletion(t *testing.T, ctx *testContext, ns *v1.Namespace, definition *apiextensionsv1.CustomResourceDefinition, resourceClient dynamic.ResourceInterface) {
|
||||||
clientSet, apiExtensionClient := ctx.clientSet, ctx.apiExtensionClient
|
clientSet, apiExtensionClient := ctx.clientSet, ctx.apiExtensionClient
|
||||||
|
|
||||||
configMapClient := clientSet.CoreV1().ConfigMaps(ns.Name)
|
configMapClient := clientSet.CoreV1().ConfigMaps(ns.Name)
|
||||||
@ -1261,7 +1261,7 @@ func testCRDDeletion(t *testing.T, ctx *testContext, ns *v1.Namespace, definitio
|
|||||||
time.Sleep(ctx.syncPeriod + 5*time.Second)
|
time.Sleep(ctx.syncPeriod + 5*time.Second)
|
||||||
|
|
||||||
// Delete the definition, which should cascade to the owner and ultimately its dependents.
|
// Delete the definition, which should cascade to the owner and ultimately its dependents.
|
||||||
if err := apiextensionstestserver.DeleteCustomResourceDefinition(definition, apiExtensionClient); err != nil {
|
if err := apiextensionstestserver.DeleteV1CustomResourceDefinition(definition, apiExtensionClient); err != nil {
|
||||||
t.Fatalf("failed to delete %q: %v", definition.Name, err)
|
t.Fatalf("failed to delete %q: %v", definition.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,12 +89,7 @@ func CreateMultiVersionTestCRD(f *framework.Framework, group string, opts ...Opt
|
|||||||
Served: true,
|
Served: true,
|
||||||
Storage: true,
|
Storage: true,
|
||||||
Name: "v1",
|
Name: "v1",
|
||||||
Schema: &apiextensionsv1.CustomResourceValidation{
|
Schema: fixtures.AllowAllSchema(),
|
||||||
OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{
|
|
||||||
XPreserveUnknownFields: pointer.BoolPtr(true),
|
|
||||||
Type: "object",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user