mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 19:01:49 +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"
|
||||
"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"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
@ -34,43 +34,50 @@ func TestAPIApproval(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if noxuAPIApproved := findCRDCondition(noxuDefinition, apiextensionsv1beta1.KubernetesAPIApprovalPolicyConformant); noxuAPIApproved != nil {
|
||||
if noxuAPIApproved := findCRDCondition(noxuDefinition, apiextensionsv1.KubernetesAPIApprovalPolicyConformant); noxuAPIApproved != nil {
|
||||
t.Fatal(noxuAPIApproved)
|
||||
}
|
||||
|
||||
newSigKubeAPIFn := func(resource, approvalAnnotation string) *apiextensionsv1beta1.CustomResourceDefinition {
|
||||
return &apiextensionsv1beta1.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: resource + ".sigs.k8s.io", Annotations: map[string]string{apiextensionsv1beta1.KubeAPIApprovedAnnotation: approvalAnnotation}},
|
||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||
Group: "sigs.k8s.io",
|
||||
Version: "v1beta1",
|
||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||
newSigKubeAPIFn := func(resource, approvalAnnotation string) *apiextensionsv1.CustomResourceDefinition {
|
||||
return &apiextensionsv1.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: resource + ".sigs.k8s.io", Annotations: map[string]string{apiextensionsv1.KubeAPIApprovedAnnotation: approvalAnnotation}},
|
||||
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||
Group: "sigs.k8s.io",
|
||||
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "v1beta1",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
Schema: fixtures.AllowAllSchema(),
|
||||
},
|
||||
},
|
||||
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||
Plural: resource,
|
||||
Singular: resource + "singular",
|
||||
Kind: resource + "Kind",
|
||||
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
|
||||
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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
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 {
|
||||
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)
|
||||
return false, nil
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
"fmt"
|
||||
"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/test/integration/fixtures"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
@ -50,14 +50,14 @@ func TestApplyBasic(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
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()
|
||||
yamlBody := []byte(fmt.Sprintf(`
|
||||
@ -70,7 +70,7 @@ values:
|
||||
boolVal: true
|
||||
stringVal: "1"`, apiVersion, kind))
|
||||
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").
|
||||
Param("fieldManager", "apply_test").
|
||||
Body(yamlBody).
|
||||
@ -80,7 +80,7 @@ values:
|
||||
}
|
||||
|
||||
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").
|
||||
Body([]byte(`{"values":{"numVal": 5}}`)).
|
||||
DoRaw(context.TODO())
|
||||
@ -90,7 +90,7 @@ values:
|
||||
|
||||
// Re-apply the same object, we should get conflicts now.
|
||||
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").
|
||||
Param("fieldManager", "apply_test").
|
||||
Body(yamlBody).
|
||||
@ -108,7 +108,7 @@ values:
|
||||
|
||||
// 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).
|
||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||
Name("mytest").
|
||||
Param("force", "true").
|
||||
Param("fieldManager", "apply_test").
|
||||
|
@ -25,7 +25,7 @@ import (
|
||||
"testing"
|
||||
"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/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
@ -56,8 +56,8 @@ func TestNamespaceScopedCRUD(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -75,8 +75,8 @@ func TestClusterScopedCRUD(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -86,7 +86,7 @@ func TestClusterScopedCRUD(t *testing.T) {
|
||||
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{}
|
||||
noxuWatchs := map[string]watch.Interface{}
|
||||
disabledVersions := map[string]bool{}
|
||||
@ -321,8 +321,8 @@ func TestInvalidCRUD(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
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)
|
||||
initialList, err := noxuResourceClient.List(context.TODO(), metav1.ListOptions{})
|
||||
if err != nil {
|
||||
@ -527,9 +527,9 @@ func TestDiscovery(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
scope := apiextensionsv1beta1.NamespaceScoped
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(scope)
|
||||
if _, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient); err != nil {
|
||||
scope := apiextensionsv1.NamespaceScoped
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(scope)
|
||||
if _, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -574,8 +574,8 @@ func TestNoNamespaceReject(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -593,7 +593,7 @@ func TestNoNamespaceReject(t *testing.T) {
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
||||
if e, a := noxuDefinition.Spec.Names.ListKind, initialListTypeMeta.GetKind(); e != a {
|
||||
@ -613,8 +613,8 @@ func TestSameNameDiffNamespace(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -636,8 +636,8 @@ func TestSelfLink(t *testing.T) {
|
||||
defer tearDown()
|
||||
|
||||
// namespace scoped
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -656,8 +656,8 @@ func TestSelfLink(t *testing.T) {
|
||||
}
|
||||
|
||||
// cluster scoped
|
||||
curletDefinition := fixtures.NewCurletCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
||||
curletDefinition, err = fixtures.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient)
|
||||
curletDefinition := fixtures.NewCurletV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||
curletDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -682,8 +682,8 @@ func TestPreserveInt(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -724,8 +724,8 @@ func TestPatch(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -802,8 +802,8 @@ func TestCrossNamespaceListWatch(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -881,7 +881,7 @@ func TestCrossNamespaceListWatch(t *testing.T) {
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
||||
if e, a := noxuDefinition.Spec.Names.Kind, createdTypeMeta.GetKind(); e != a {
|
||||
@ -901,7 +901,7 @@ func TestCrossNamespaceListWatch(t *testing.T) {
|
||||
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)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create noxu Instance:%v", err)
|
||||
@ -944,27 +944,27 @@ func TestNameConflict(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
noxu2Definition := fixtures.NewNoxu2CustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
||||
_, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Create(context.TODO(), noxu2Definition, metav1.CreateOptions{})
|
||||
noxu2Definition := fixtures.NewNoxu2CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||
_, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Create(context.TODO(), noxu2Definition, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// A NameConflict occurs
|
||||
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 {
|
||||
return false, err
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -974,20 +974,20 @@ func TestNameConflict(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient)
|
||||
err = fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Names are now accepted
|
||||
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 {
|
||||
return false, err
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -1005,15 +1005,15 @@ func TestStatusGetAndPatch(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// make sure we don't get 405 Method Not Allowed from Getting CRD/status subresource
|
||||
result := &apiextensionsv1beta1.CustomResourceDefinition{}
|
||||
err = apiExtensionClient.ApiextensionsV1beta1().RESTClient().Get().
|
||||
result := &apiextensionsv1.CustomResourceDefinition{}
|
||||
err = apiExtensionClient.ApiextensionsV1().RESTClient().Get().
|
||||
Resource("customresourcedefinitions").
|
||||
Name(noxuDefinition.Name).
|
||||
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
|
||||
_, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().
|
||||
_, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().
|
||||
Patch(context.TODO(), noxuDefinition.Name, types.StrategicMergePatchType,
|
||||
[]byte(fmt.Sprintf(`{"labels":{"test-label":"dummy"}}`)), metav1.PatchOptions{},
|
||||
"status")
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
"testing"
|
||||
"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/test/integration/fixtures"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
@ -50,8 +50,8 @@ func TestChangeCRD(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionsClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionsClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -76,7 +76,7 @@ func TestChangeCRD(t *testing.T) {
|
||||
|
||||
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 {
|
||||
t.Error(err)
|
||||
continue
|
||||
@ -90,7 +90,7 @@ func TestChangeCRD(t *testing.T) {
|
||||
} else {
|
||||
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)
|
||||
continue
|
||||
}
|
||||
|
@ -335,10 +335,8 @@ func validateNonTrivialConverted(t *testing.T, ctc *conversionTestContext) {
|
||||
client := ctc.versionedClient(ns, createVersion.Name)
|
||||
|
||||
fixture := newConversionMultiVersionFixture(ns, name, createVersion.Name)
|
||||
if !*ctc.crd.Spec.PreserveUnknownFields {
|
||||
if err := unstructured.SetNestedField(fixture.Object, "foo", "garbage"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := unstructured.SetNestedField(fixture.Object, "foo", "garbage"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := client.Create(context.TODO(), fixture, metav1.CreateOptions{}); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -393,10 +391,8 @@ func validateNonTrivialConvertedList(t *testing.T, ctc *conversionTestContext) {
|
||||
name := "converted-" + createVersion.Name
|
||||
client := ctc.versionedClient(ns, createVersion.Name)
|
||||
fixture := newConversionMultiVersionFixture(ns, name, createVersion.Name)
|
||||
if !*ctc.crd.Spec.PreserveUnknownFields {
|
||||
if err := unstructured.SetNestedField(fixture.Object, "foo", "garbage"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := unstructured.SetNestedField(fixture.Object, "foo", "garbage"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err := client.Create(context.TODO(), fixture, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
@ -428,10 +424,6 @@ func validateNonTrivialConvertedList(t *testing.T, ctc *conversionTestContext) {
|
||||
}
|
||||
|
||||
func validateStoragePruning(t *testing.T, ctc *conversionTestContext) {
|
||||
if *ctc.crd.Spec.PreserveUnknownFields {
|
||||
return
|
||||
}
|
||||
|
||||
ns := ctc.namespace
|
||||
|
||||
for _, createVersion := range ctc.crd.Spec.Versions {
|
||||
@ -905,13 +897,13 @@ func newConversionTestContext(t *testing.T, apiExtensionsClient clientset.Interf
|
||||
if err != nil {
|
||||
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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tearDown := func() {
|
||||
if err := fixtures.DeleteCustomResourceDefinition(crd, apiExtensionsClient); err != nil {
|
||||
if err := fixtures.DeleteV1CustomResourceDefinition(crd, apiExtensionsClient); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -923,13 +915,13 @@ type conversionTestContext struct {
|
||||
namespace string
|
||||
apiExtensionsClient clientset.Interface
|
||||
dynamicClient dynamic.Interface
|
||||
crd *apiextensionsv1beta1.CustomResourceDefinition
|
||||
crd *apiextensionsv1.CustomResourceDefinition
|
||||
etcdObjectReader *storage.EtcdObjectReader
|
||||
}
|
||||
|
||||
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}
|
||||
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)
|
||||
@ -943,17 +935,19 @@ func (c *conversionTestContext) versionedClients(ns string) map[string]dynamic.R
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *conversionTestContext) setConversionWebhook(t *testing.T, webhookClientConfig *apiextensionsv1beta1.WebhookClientConfig, reviewVersions []string) {
|
||||
crd, err := c.apiExtensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(context.TODO(), c.crd.Name, metav1.GetOptions{})
|
||||
func (c *conversionTestContext) setConversionWebhook(t *testing.T, webhookClientConfig *apiextensionsv1.WebhookClientConfig, reviewVersions []string) {
|
||||
crd, err := c.apiExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), c.crd.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
crd.Spec.Conversion = &apiextensionsv1beta1.CustomResourceConversion{
|
||||
Strategy: apiextensionsv1beta1.WebhookConverter,
|
||||
WebhookClientConfig: webhookClientConfig,
|
||||
ConversionReviewVersions: reviewVersions,
|
||||
crd.Spec.Conversion = &apiextensionsv1.CustomResourceConversion{
|
||||
Strategy: apiextensionsv1.WebhookConverter,
|
||||
Webhook: &apiextensionsv1.WebhookConversion{
|
||||
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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -962,15 +956,15 @@ func (c *conversionTestContext) setConversionWebhook(t *testing.T, webhookClient
|
||||
}
|
||||
|
||||
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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
crd.Spec.Conversion = &apiextensionsv1beta1.CustomResourceConversion{
|
||||
Strategy: apiextensionsv1beta1.NoneConverter,
|
||||
crd.Spec.Conversion = &apiextensionsv1.CustomResourceConversion{
|
||||
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 {
|
||||
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) {
|
||||
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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i, v := range crd.Spec.Versions {
|
||||
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 {
|
||||
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) {
|
||||
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 {
|
||||
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, 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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ import (
|
||||
|
||||
// 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.
|
||||
func StartConversionWebhookServer(handler http.Handler) (func(), *apiextensionsv1beta1.WebhookClientConfig, error) {
|
||||
func StartConversionWebhookServer(handler http.Handler) (func(), *apiextensionsv1.WebhookClientConfig, error) {
|
||||
roots := x509.NewCertPool()
|
||||
if !roots.AppendCertsFromPEM(localhostCert) {
|
||||
return nil, nil, fmt.Errorf("failed to append Cert from PEM")
|
||||
@ -57,7 +57,7 @@ func StartConversionWebhookServer(handler http.Handler) (func(), *apiextensionsv
|
||||
}
|
||||
webhookServer.StartTLS()
|
||||
endpoint := webhookServer.URL + "/convert"
|
||||
webhookConfig := &apiextensionsv1beta1.WebhookClientConfig{
|
||||
webhookConfig := &apiextensionsv1.WebhookClientConfig{
|
||||
CABundle: localhostCert,
|
||||
URL: &endpoint,
|
||||
}
|
||||
|
@ -23,8 +23,7 @@ import (
|
||||
|
||||
"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/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@ -36,8 +35,8 @@ func TestFinalization(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
require.NoError(t, err)
|
||||
|
||||
ns := "not-the-default"
|
||||
@ -100,8 +99,8 @@ func TestFinalizationAndDeletion(t *testing.T) {
|
||||
defer tearDown()
|
||||
|
||||
// Create a CRD.
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create a CR with a finalizer.
|
||||
@ -129,7 +128,7 @@ func TestFinalizationAndDeletion(t *testing.T) {
|
||||
require.NotNil(t, gottenNoxuInstance.GetDeletionTimestamp())
|
||||
|
||||
// Delete the CRD.
|
||||
fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient)
|
||||
fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient)
|
||||
|
||||
// Check is CR still there after the CRD deletion.
|
||||
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 = 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
|
||||
})
|
||||
if !errors.IsNotFound(err) {
|
||||
|
@ -44,6 +44,16 @@ const (
|
||||
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
|
||||
func NewRandomNameV1CustomResourceDefinition(scope apiextensionsv1.ResourceScope) *apiextensionsv1.CustomResourceDefinition {
|
||||
// ensure the singular doesn't end in an s for now
|
||||
@ -57,12 +67,7 @@ func NewRandomNameV1CustomResourceDefinition(scope apiextensionsv1.ResourceScope
|
||||
Name: "v1beta1",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
Schema: &apiextensionsv1.CustomResourceValidation{
|
||||
OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{
|
||||
XPreserveUnknownFields: pointer.BoolPtr(true),
|
||||
Type: "object",
|
||||
},
|
||||
},
|
||||
Schema: AllowAllSchema(),
|
||||
},
|
||||
},
|
||||
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.
|
||||
func NewNoxuV1CustomResourceDefinition(scope apiextensionsv1.ResourceScope) *apiextensionsv1.CustomResourceDefinition {
|
||||
return &apiextensionsv1.CustomResourceDefinition{
|
||||
@ -126,12 +91,7 @@ func NewNoxuV1CustomResourceDefinition(scope apiextensionsv1.ResourceScope) *api
|
||||
Name: "v1beta1",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
Schema: &apiextensionsv1.CustomResourceValidation{
|
||||
OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{
|
||||
XPreserveUnknownFields: pointer.BoolPtr(true),
|
||||
Type: "object",
|
||||
},
|
||||
},
|
||||
Schema: AllowAllSchema(),
|
||||
}},
|
||||
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||
Plural: "noxus",
|
||||
@ -173,13 +133,12 @@ func NewNoxuInstance(namespace, name string) *unstructured.Unstructured {
|
||||
}
|
||||
|
||||
// NewMultipleVersionNoxuCRD returns a WishIHadChosenNoxu with multiple versions.
|
||||
func NewMultipleVersionNoxuCRD(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition {
|
||||
return &apiextensionsv1beta1.CustomResourceDefinition{
|
||||
func NewMultipleVersionNoxuCRD(scope apiextensionsv1.ResourceScope) *apiextensionsv1.CustomResourceDefinition {
|
||||
return &apiextensionsv1.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"},
|
||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||
Group: "mygroup.example.com",
|
||||
Version: "v1beta1",
|
||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||
Group: "mygroup.example.com",
|
||||
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||
Plural: "noxus",
|
||||
Singular: "nonenglishnoxu",
|
||||
Kind: "WishIHadChosenNoxu",
|
||||
@ -188,38 +147,52 @@ func NewMultipleVersionNoxuCRD(scope apiextensionsv1beta1.ResourceScope) *apiext
|
||||
Categories: []string{"all"},
|
||||
},
|
||||
Scope: scope,
|
||||
Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{
|
||||
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "v1beta1",
|
||||
Served: true,
|
||||
Storage: false,
|
||||
Subresources: &apiextensionsv1.CustomResourceSubresources{
|
||||
Status: &apiextensionsv1.CustomResourceSubresourceStatus{},
|
||||
},
|
||||
Schema: AllowAllSchema(),
|
||||
},
|
||||
{
|
||||
Name: "v1beta2",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
Subresources: &apiextensionsv1.CustomResourceSubresources{
|
||||
Status: &apiextensionsv1.CustomResourceSubresourceStatus{},
|
||||
},
|
||||
Schema: AllowAllSchema(),
|
||||
},
|
||||
{
|
||||
Name: "v0",
|
||||
Served: false,
|
||||
Storage: false,
|
||||
Subresources: &apiextensionsv1.CustomResourceSubresources{
|
||||
Status: &apiextensionsv1.CustomResourceSubresourceStatus{},
|
||||
},
|
||||
Schema: AllowAllSchema(),
|
||||
},
|
||||
},
|
||||
Subresources: &apiextensionsv1beta1.CustomResourceSubresources{
|
||||
Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// NewNoxu2CustomResourceDefinition returns a WishIHadChosenNoxu2 CRD.
|
||||
func NewNoxu2CustomResourceDefinition(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition {
|
||||
return &apiextensionsv1beta1.CustomResourceDefinition{
|
||||
func NewNoxu2CustomResourceDefinition(scope apiextensionsv1.ResourceScope) *apiextensionsv1.CustomResourceDefinition {
|
||||
return &apiextensionsv1.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "noxus2.mygroup.example.com"},
|
||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||
Group: "mygroup.example.com",
|
||||
Version: "v1alpha1",
|
||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||
Group: "mygroup.example.com",
|
||||
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{{
|
||||
Name: "v1alpha1",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
Schema: AllowAllSchema(),
|
||||
}},
|
||||
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||
Plural: "noxus2",
|
||||
Singular: "nonenglishnoxu2",
|
||||
Kind: "WishIHadChosenNoxu2",
|
||||
@ -231,14 +204,21 @@ func NewNoxu2CustomResourceDefinition(scope apiextensionsv1beta1.ResourceScope)
|
||||
}
|
||||
}
|
||||
|
||||
// NewCurletCustomResourceDefinition returns a Curlet CRD.
|
||||
func NewCurletCustomResourceDefinition(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition {
|
||||
return &apiextensionsv1beta1.CustomResourceDefinition{
|
||||
// NewCurletV1CustomResourceDefinition returns a Curlet CRD.
|
||||
func NewCurletV1CustomResourceDefinition(scope apiextensionsv1.ResourceScope) *apiextensionsv1.CustomResourceDefinition {
|
||||
return &apiextensionsv1.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "curlets.mygroup.example.com"},
|
||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||
Group: "mygroup.example.com",
|
||||
Version: "v1beta1",
|
||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||
Group: "mygroup.example.com",
|
||||
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "v1beta1",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
Schema: AllowAllSchema(),
|
||||
},
|
||||
},
|
||||
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||
Plural: "curlets",
|
||||
Singular: "curlet",
|
||||
Kind: "Curlet",
|
||||
@ -506,23 +486,6 @@ func isWatchCachePrimed(crd *apiextensionsv1.CustomResourceDefinition, dynamicCl
|
||||
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.
|
||||
func DeleteV1CustomResourceDefinition(crd *apiextensionsv1.CustomResourceDefinition, apiExtensionsClient clientset.Interface) error {
|
||||
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.
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -20,9 +20,15 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
serveroptions "k8s.io/apiextensions-apiserver/pkg/cmd/server/options"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
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
|
||||
}
|
||||
|
||||
// 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.
|
||||
func IntegrationEtcdServers() []string {
|
||||
if etcdURL, ok := os.LookupEnv("KUBE_INTEGRATION_ETCD_URL"); ok {
|
||||
|
@ -22,7 +22,6 @@ import (
|
||||
"testing"
|
||||
|
||||
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/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
@ -34,11 +33,11 @@ import (
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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{})
|
||||
if err != nil {
|
||||
t.Logf("%#v", createdInstance)
|
||||
@ -65,28 +64,28 @@ func instantiateVersionedCustomResource(t *testing.T, instanceToCreate *unstruct
|
||||
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}
|
||||
|
||||
if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped {
|
||||
if crd.Spec.Scope != apiextensionsv1.ClusterScoped {
|
||||
return client.Resource(gvr).Namespace(ns)
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
// 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++ {
|
||||
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 {
|
||||
return nil, fmt.Errorf("failed to get CustomResourceDefinition %q: %v", name, err)
|
||||
}
|
||||
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 {
|
||||
return crd, nil
|
||||
}
|
||||
@ -117,13 +116,7 @@ func UpdateV1CustomResourceDefinitionWithRetry(client clientset.Interface, name
|
||||
}
|
||||
|
||||
// getSchemaForVersion returns the validation schema for given version in given CRD.
|
||||
func getSchemaForVersion(crd *apiextensionsv1beta1.CustomResourceDefinition, version string) (*apiextensionsv1beta1.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)
|
||||
}
|
||||
func getSchemaForVersion(crd *apiextensionsv1.CustomResourceDefinition, version string) (*apiextensionsv1.CustomResourceValidation, error) {
|
||||
for _, v := range crd.Spec.Versions {
|
||||
if version == v.Name {
|
||||
return v.Schema, nil
|
||||
@ -133,13 +126,7 @@ func getSchemaForVersion(crd *apiextensionsv1beta1.CustomResourceDefinition, ver
|
||||
}
|
||||
|
||||
// getSubresourcesForVersion returns the subresources for given version in given CRD.
|
||||
func getSubresourcesForVersion(crd *apiextensionsv1beta1.CustomResourceDefinition, version string) (*apiextensionsv1beta1.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)
|
||||
}
|
||||
func getSubresourcesForVersion(crd *apiextensionsv1.CustomResourceDefinition, version string) (*apiextensionsv1.CustomResourceSubresources, error) {
|
||||
for _, v := range crd.Spec.Versions {
|
||||
if version == v.Name {
|
||||
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.
|
||||
// One cannot mutate the original CRD columns using the logically-defaulted columns. Please iterate through
|
||||
// the original CRD object instead.
|
||||
func getColumnsForVersion(crd *apiextensionsv1beta1.CustomResourceDefinition, version string) ([]apiextensionsv1beta1.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)
|
||||
}
|
||||
func getColumnsForVersion(crd *apiextensionsv1.CustomResourceDefinition, version string) ([]apiextensionsv1.CustomResourceColumnDefinition, error) {
|
||||
for _, v := range crd.Spec.Versions {
|
||||
if version == v.Name {
|
||||
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.
|
||||
// One cannot mutate the original CRD columns using the logically-defaulted columns. Please iterate through
|
||||
// the original CRD object instead.
|
||||
func serveDefaultColumnsIfEmpty(columns []apiextensionsv1beta1.CustomResourceColumnDefinition) []apiextensionsv1beta1.CustomResourceColumnDefinition {
|
||||
func serveDefaultColumnsIfEmpty(columns []apiextensionsv1.CustomResourceColumnDefinition) []apiextensionsv1.CustomResourceColumnDefinition {
|
||||
if len(columns) > 0 {
|
||||
return columns
|
||||
}
|
||||
return []apiextensionsv1beta1.CustomResourceColumnDefinition{
|
||||
return []apiextensionsv1.CustomResourceColumnDefinition{
|
||||
{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"
|
||||
"testing"
|
||||
|
||||
"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/test/integration/fixtures"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/dynamic"
|
||||
)
|
||||
|
||||
func TestLimits(t *testing.T) {
|
||||
@ -47,14 +46,14 @@ func TestLimits(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
@ -70,7 +69,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind))
|
||||
_, err := rest.Post().
|
||||
SetHeader("Accept", "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).
|
||||
DoRaw(context.TODO())
|
||||
if !apierrors.IsRequestEntityTooLargeError(err) {
|
||||
@ -93,7 +92,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind))
|
||||
_, err := rest.Post().
|
||||
SetHeader("Accept", "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).
|
||||
DoRaw(context.TODO())
|
||||
if !apierrors.IsBadRequest(err) {
|
||||
@ -116,7 +115,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind))
|
||||
_, err := rest.Post().
|
||||
SetHeader("Accept", "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).
|
||||
DoRaw(context.TODO())
|
||||
if !apierrors.IsBadRequest(err) {
|
||||
@ -137,7 +136,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind))
|
||||
_, err := rest.Post().
|
||||
SetHeader("Accept", "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).
|
||||
DoRaw(context.TODO())
|
||||
if !apierrors.IsRequestEntityTooLargeError(err) {
|
||||
@ -161,7 +160,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind))
|
||||
_, err := rest.Post().
|
||||
SetHeader("Accept", "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).
|
||||
DoRaw(context.TODO())
|
||||
if !apierrors.IsBadRequest(err) {
|
||||
@ -185,7 +184,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind))
|
||||
_, err := rest.Post().
|
||||
SetHeader("Accept", "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).
|
||||
DoRaw(context.TODO())
|
||||
if !apierrors.IsBadRequest(err) {
|
||||
@ -196,7 +195,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind))
|
||||
// Create instance to allow patching
|
||||
{
|
||||
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 {
|
||||
t.Fatalf("error creating object: %v", err)
|
||||
}
|
||||
@ -207,7 +206,7 @@ values: `+strings.Repeat("[", 3*1024*1024), apiVersion, kind))
|
||||
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) + `}]`)
|
||||
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()
|
||||
if !apierrors.IsBadRequest(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")
|
||||
}
|
||||
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()
|
||||
if !apierrors.IsBadRequest(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")
|
||||
}
|
||||
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()
|
||||
if !apierrors.IsBadRequest(err) {
|
||||
t.Errorf("expected bad request err, got %#v", err)
|
||||
|
@ -22,37 +22,36 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"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"
|
||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"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"},
|
||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||
Group: "tests.example.com",
|
||||
Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{
|
||||
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "v1beta1",
|
||||
Storage: true,
|
||||
Served: true,
|
||||
Schema: fixtures.AllowAllSchema(),
|
||||
},
|
||||
},
|
||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||
Plural: "foos",
|
||||
Singular: "foo",
|
||||
Kind: "Foo",
|
||||
ListKind: "FooList",
|
||||
},
|
||||
Scope: apiextensionsv1beta1.ClusterScoped,
|
||||
Validation: &apiextensionsv1beta1.CustomResourceValidation{},
|
||||
Scope: apiextensionsv1.ClusterScoped,
|
||||
},
|
||||
}
|
||||
|
||||
@ -128,11 +127,11 @@ func TestListTypes(t *testing.T) {
|
||||
defer tearDownFn()
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
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")
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
s := crd.Spec.Validation.OpenAPIV3Schema.Properties["correct-map"]
|
||||
s := crd.Spec.Versions[0].Schema.OpenAPIV3Schema.Properties["correct-map"]
|
||||
s.XListMapKeys = []string{"a"}
|
||||
crd.Spec.Validation.OpenAPIV3Schema.Properties["correct-map"] = s
|
||||
_, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{})
|
||||
crd.Spec.Versions[0].Schema.OpenAPIV3Schema.Properties["correct-map"] = s
|
||||
_, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{})
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -30,7 +30,6 @@ import (
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
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"
|
||||
serveroptions "k8s.io/apiextensions-apiserver/pkg/cmd/server/options"
|
||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||
@ -52,8 +51,8 @@ func TestPostInvalidObjectMeta(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -114,11 +113,11 @@ func TestInvalidObjectMetaInStorage(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinition.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{
|
||||
OpenAPIV3Schema: &apiextensionsv1beta1.JSONSchemaProps{
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||
noxuDefinition.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{
|
||||
OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{
|
||||
Type: "object",
|
||||
Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
|
||||
Properties: map[string]apiextensionsv1.JSONSchemaProps{
|
||||
"embedded": {
|
||||
Type: "object",
|
||||
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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
|
||||
"go.etcd.io/etcd/clientv3"
|
||||
"go.etcd.io/etcd/pkg/transport"
|
||||
"google.golang.org/grpc"
|
||||
@ -39,29 +41,37 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/json"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"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/test/integration/fixtures"
|
||||
)
|
||||
|
||||
var pruningFixture = &apiextensionsv1beta1.CustomResourceDefinition{
|
||||
var pruningFixture = &apiextensionsv1.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foos.tests.example.com"},
|
||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||
Group: "tests.example.com",
|
||||
Version: "v1beta1",
|
||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||
Group: "tests.example.com",
|
||||
Scope: apiextensionsv1.ClusterScoped,
|
||||
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",
|
||||
Singular: "foo",
|
||||
Kind: "Foo",
|
||||
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()
|
||||
|
||||
crd := pruningFixture.DeepCopy()
|
||||
crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{}
|
||||
if err := yaml.Unmarshal([]byte(fooSchema), &crd.Spec.Validation.OpenAPIV3Schema); err != nil {
|
||||
crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{}
|
||||
if err := yaml.Unmarshal([]byte(fooSchema), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
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{}
|
||||
if err := yaml.Unmarshal([]byte(pruningFooInstance), &foo.Object); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -241,18 +251,18 @@ func TestPruningStatus(t *testing.T) {
|
||||
defer tearDownFn()
|
||||
|
||||
crd := pruningFixture.DeepCopy()
|
||||
crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{}
|
||||
if err := yaml.Unmarshal([]byte(fooStatusSchema), &crd.Spec.Validation.OpenAPIV3Schema); err != nil {
|
||||
crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{}
|
||||
if err := yaml.Unmarshal([]byte(fooStatusSchema), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
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{}
|
||||
if err := yaml.Unmarshal([]byte(pruningFooInstance), &foo.Object); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -310,12 +320,12 @@ func TestPruningFromStorage(t *testing.T) {
|
||||
}
|
||||
|
||||
crd := pruningFixture.DeepCopy()
|
||||
crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{}
|
||||
if err := yaml.Unmarshal([]byte(fooSchema), &crd.Spec.Validation.OpenAPIV3Schema); err != nil {
|
||||
crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{}
|
||||
if err := yaml.Unmarshal([]byte(fooSchema), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -368,7 +378,7 @@ func TestPruningFromStorage(t *testing.T) {
|
||||
}
|
||||
|
||||
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{})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
@ -400,16 +410,16 @@ func TestPruningPatch(t *testing.T) {
|
||||
defer tearDownFn()
|
||||
|
||||
crd := pruningFixture.DeepCopy()
|
||||
crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{}
|
||||
if err := yaml.Unmarshal([]byte(fooSchema), &crd.Spec.Validation.OpenAPIV3Schema); err != nil {
|
||||
crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{}
|
||||
if err := yaml.Unmarshal([]byte(fooSchema), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
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{}
|
||||
if err := yaml.Unmarshal([]byte(pruningFooInstance), &foo.Object); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -451,18 +461,18 @@ func TestPruningCreatePreservingUnknownFields(t *testing.T) {
|
||||
defer tearDownFn()
|
||||
|
||||
crd := pruningFixture.DeepCopy()
|
||||
crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{}
|
||||
if err := yaml.Unmarshal([]byte(fooSchemaPreservingUnknownFields), &crd.Spec.Validation.OpenAPIV3Schema); err != nil {
|
||||
crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{}
|
||||
if err := yaml.Unmarshal([]byte(fooSchemaPreservingUnknownFields), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
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{}
|
||||
if err := yaml.Unmarshal([]byte(pruningFooInstance), &foo.Object); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -536,18 +546,18 @@ func TestPruningEmbeddedResources(t *testing.T) {
|
||||
defer tearDownFn()
|
||||
|
||||
crd := pruningFixture.DeepCopy()
|
||||
crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{}
|
||||
if err := yaml.Unmarshal([]byte(fooSchemaEmbeddedResource), &crd.Spec.Validation.OpenAPIV3Schema); err != nil {
|
||||
crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{}
|
||||
if err := yaml.Unmarshal([]byte(fooSchemaEmbeddedResource), &crd.Spec.Versions[0].Schema.OpenAPIV3Schema); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
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{}
|
||||
if err := yaml.Unmarshal([]byte(fooSchemaEmbeddedResourceInstance), &foo.Object); err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -28,7 +28,7 @@ import (
|
||||
|
||||
"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"
|
||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
@ -47,8 +47,8 @@ func TestMultipleResourceInstances(t *testing.T) {
|
||||
defer tearDown()
|
||||
|
||||
ns := "not-the-default"
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -172,8 +172,8 @@ func TestMultipleRegistration(t *testing.T) {
|
||||
|
||||
ns := "not-the-default"
|
||||
sameInstanceName := "foo"
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -191,8 +191,8 @@ func TestMultipleRegistration(t *testing.T) {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
curletDefinition := fixtures.NewCurletCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
||||
curletDefinition, err = fixtures.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient)
|
||||
curletDefinition := fixtures.NewCurletV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||
curletDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -225,11 +225,11 @@ func TestDeRegistrationAndReRegistration(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer tearDown()
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||
ns := "not-the-default"
|
||||
sameInstanceName := "foo"
|
||||
func() {
|
||||
noxuDefinition, err := fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition, err := fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -237,10 +237,10 @@ func TestDeRegistrationAndReRegistration(t *testing.T) {
|
||||
if _, err := instantiateCustomResource(t, fixtures.NewNoxuInstance(ns, sameInstanceName), noxuNamespacedResourceClient, noxuDefinition); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
||||
if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
||||
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)
|
||||
}
|
||||
if _, err = noxuNamespacedResourceClient.List(context.TODO(), metav1.ListOptions{}); err == nil || !errors.IsNotFound(err) {
|
||||
@ -252,10 +252,10 @@ func TestDeRegistrationAndReRegistration(t *testing.T) {
|
||||
}()
|
||||
|
||||
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)
|
||||
}
|
||||
noxuDefinition, err := fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition, err := fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -327,8 +327,8 @@ func TestEtcdStorage(t *testing.T) {
|
||||
etcdPrefix := s.RecommendedOptions.Etcd.StorageConfig.Prefix
|
||||
|
||||
ns1 := "another-default-is-possible"
|
||||
curletDefinition := fixtures.NewCurletCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
||||
curletDefinition, err = fixtures.CreateNewCustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient)
|
||||
curletDefinition := fixtures.NewCurletV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||
curletDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(curletDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -338,8 +338,8 @@ func TestEtcdStorage(t *testing.T) {
|
||||
}
|
||||
|
||||
ns2 := "the-cruel-default"
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -23,15 +23,14 @@ import (
|
||||
|
||||
"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"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"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) {
|
||||
@ -41,15 +40,32 @@ func TestHandlerScope(t *testing.T) {
|
||||
}
|
||||
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) {
|
||||
|
||||
crd := &apiextensionsv1beta1.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: strings.ToLower(string(scope)) + "s.test.apiextensions-apiserver.k8s.io"},
|
||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||
Group: "test.apiextensions-apiserver.k8s.io",
|
||||
Version: "v1beta1",
|
||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||
crd := &apiextensionsv1.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: strings.ToLower(string(scope)) + "s.test.apiextensions-apiserver.k8s.io",
|
||||
Annotations: map[string]string{"api-approved.kubernetes.io": "unapproved, test-only"},
|
||||
},
|
||||
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",
|
||||
Singular: strings.ToLower(string(scope)),
|
||||
Kind: string(scope),
|
||||
@ -58,14 +74,7 @@ func TestHandlerScope(t *testing.T) {
|
||||
Scope: scope,
|
||||
},
|
||||
}
|
||||
crd.Spec.Subresources = &apiextensionsv1beta1.CustomResourceSubresources{
|
||||
Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{},
|
||||
Scale: &apiextensionsv1beta1.CustomResourceSubresourceScale{
|
||||
SpecReplicasPath: ".spec.replicas",
|
||||
StatusReplicasPath: ".status.replicas",
|
||||
},
|
||||
}
|
||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -75,7 +84,7 @@ func TestHandlerScope(t *testing.T) {
|
||||
ns := "test"
|
||||
var client dynamic.ResourceInterface = dynamicClient.Resource(gvr)
|
||||
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
|
||||
}
|
||||
|
||||
@ -141,7 +150,7 @@ func TestHandlerScope(t *testing.T) {
|
||||
err = otherScopeClient.DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{})
|
||||
assert.True(t, apierrors.IsNotFound(err))
|
||||
|
||||
if scope == apiextensionsv1beta1.ClusterScoped {
|
||||
if scope == apiextensionsv1.ClusterScoped {
|
||||
_, err = otherScopeClient.List(context.TODO(), metav1.ListOptions{})
|
||||
assert.True(t, apierrors.IsNotFound(err))
|
||||
|
||||
|
@ -35,7 +35,7 @@ import (
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"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/test/integration/fixtures"
|
||||
)
|
||||
@ -43,51 +43,14 @@ import (
|
||||
var labelSelectorPath = ".status.labelSelector"
|
||||
var anotherLabelSelectorPath = ".status.anotherLabelSelector"
|
||||
|
||||
func NewNoxuSubresourcesCRDs(scope apiextensionsv1beta1.ResourceScope) []*apiextensionsv1beta1.CustomResourceDefinition {
|
||||
return []*apiextensionsv1beta1.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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
func NewNoxuSubresourcesCRDs(scope apiextensionsv1.ResourceScope) []*apiextensionsv1.CustomResourceDefinition {
|
||||
return []*apiextensionsv1.CustomResourceDefinition{
|
||||
// CRD that uses per-version subresources
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"},
|
||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||
Group: "mygroup.example.com",
|
||||
Version: "v1beta1",
|
||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||
Group: "mygroup.example.com",
|
||||
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||
Plural: "noxus",
|
||||
Singular: "nonenglishnoxu",
|
||||
Kind: "WishIHadChosenNoxu",
|
||||
@ -95,32 +58,34 @@ func NewNoxuSubresourcesCRDs(scope apiextensionsv1beta1.ResourceScope) []*apiext
|
||||
ListKind: "NoxuItemList",
|
||||
},
|
||||
Scope: scope,
|
||||
Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{
|
||||
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "v1beta1",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
Subresources: &apiextensionsv1beta1.CustomResourceSubresources{
|
||||
Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{},
|
||||
Scale: &apiextensionsv1beta1.CustomResourceSubresourceScale{
|
||||
Subresources: &apiextensionsv1.CustomResourceSubresources{
|
||||
Status: &apiextensionsv1.CustomResourceSubresourceStatus{},
|
||||
Scale: &apiextensionsv1.CustomResourceSubresourceScale{
|
||||
SpecReplicasPath: ".spec.replicas",
|
||||
StatusReplicasPath: ".status.replicas",
|
||||
LabelSelectorPath: &labelSelectorPath,
|
||||
},
|
||||
},
|
||||
Schema: fixtures.AllowAllSchema(),
|
||||
},
|
||||
{
|
||||
Name: "v1",
|
||||
Served: true,
|
||||
Storage: false,
|
||||
Subresources: &apiextensionsv1beta1.CustomResourceSubresources{
|
||||
Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{},
|
||||
Scale: &apiextensionsv1beta1.CustomResourceSubresourceScale{
|
||||
Subresources: &apiextensionsv1.CustomResourceSubresources{
|
||||
Status: &apiextensionsv1.CustomResourceSubresourceStatus{},
|
||||
Scale: &apiextensionsv1.CustomResourceSubresourceScale{
|
||||
SpecReplicasPath: ".spec.replicas",
|
||||
StatusReplicasPath: ".status.replicas",
|
||||
LabelSelectorPath: &anotherLabelSelectorPath,
|
||||
},
|
||||
},
|
||||
Schema: fixtures.AllowAllSchema(),
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -155,9 +120,9 @@ func TestStatusSubresource(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped)
|
||||
for _, noxuDefinition := range noxuDefinitions {
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -254,7 +219,7 @@ func TestStatusSubresource(t *testing.T) {
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -281,7 +246,7 @@ func TestScaleSubresource(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped)
|
||||
for _, noxuDefinition := range noxuDefinitions {
|
||||
for _, v := range noxuDefinition.Spec.Versions {
|
||||
// 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
|
||||
subresources.Scale.SpecReplicasPath = "foo,bar"
|
||||
_, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
_, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err == nil {
|
||||
t.Fatalf("unexpected non-error: specReplicasPath should be a valid json path under .spec")
|
||||
}
|
||||
|
||||
subresources.Scale.SpecReplicasPath = ".spec.replicas"
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -400,7 +365,7 @@ func TestScaleSubresource(t *testing.T) {
|
||||
t.Fatalf("unexpected non-error: .spec.replicas should be less than 2147483647")
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -423,22 +388,16 @@ func TestValidationSchemaWithStatus(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// fields other than properties in root schema are not allowed
|
||||
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`)
|
||||
}
|
||||
noxuDefinition := newNoxuValidationCRDs()[0]
|
||||
|
||||
// make sure we are not restricting fields to properties even in subschemas
|
||||
noxuDefinition.Spec.Validation.OpenAPIV3Schema = &apiextensionsv1beta1.JSONSchemaProps{
|
||||
Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
|
||||
noxuDefinition.Spec.Versions[0].Schema.OpenAPIV3Schema = &apiextensionsv1.JSONSchemaProps{
|
||||
Type: "object",
|
||||
Properties: map[string]apiextensionsv1.JSONSchemaProps{
|
||||
"spec": {
|
||||
Type: "object",
|
||||
Description: "Validation for spec",
|
||||
Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
|
||||
Properties: map[string]apiextensionsv1.JSONSchemaProps{
|
||||
"replicas": {
|
||||
Type: "integer",
|
||||
},
|
||||
@ -448,7 +407,9 @@ func TestValidationSchemaWithStatus(t *testing.T) {
|
||||
Required: []string{"spec"},
|
||||
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 {
|
||||
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
|
||||
|
||||
// max value of spec.num = 10 and status.num = 10
|
||||
schema := &apiextensionsv1beta1.JSONSchemaProps{
|
||||
Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
|
||||
schema := &apiextensionsv1.JSONSchemaProps{
|
||||
Type: "object",
|
||||
Properties: map[string]apiextensionsv1.JSONSchemaProps{
|
||||
"spec": {
|
||||
Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
|
||||
Type: "object",
|
||||
Properties: map[string]apiextensionsv1.JSONSchemaProps{
|
||||
"num": {
|
||||
Type: "integer",
|
||||
Maximum: float64Ptr(10),
|
||||
@ -479,7 +442,8 @@ func TestValidateOnlyStatus(t *testing.T) {
|
||||
},
|
||||
},
|
||||
"status": {
|
||||
Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
|
||||
Type: "object",
|
||||
Properties: map[string]apiextensionsv1.JSONSchemaProps{
|
||||
"num": {
|
||||
Type: "integer",
|
||||
Maximum: float64Ptr(10),
|
||||
@ -489,24 +453,16 @@ func TestValidateOnlyStatus(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped)
|
||||
for i, noxuDefinition := range noxuDefinitions {
|
||||
if i == 0 {
|
||||
noxuDefinition.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{
|
||||
OpenAPIV3Schema: schema,
|
||||
}
|
||||
} else {
|
||||
noxuDefinition.Spec.Versions[0].Schema = &apiextensionsv1beta1.CustomResourceValidation{
|
||||
OpenAPIV3Schema: schema,
|
||||
}
|
||||
schemaWithDescription := schema.DeepCopy()
|
||||
schemaWithDescription.Description = "test"
|
||||
noxuDefinition.Spec.Versions[1].Schema = &apiextensionsv1beta1.CustomResourceValidation{
|
||||
OpenAPIV3Schema: schemaWithDescription,
|
||||
}
|
||||
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped)
|
||||
for _, noxuDefinition := range noxuDefinitions {
|
||||
noxuDefinition.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{
|
||||
OpenAPIV3Schema: schema.DeepCopy(),
|
||||
}
|
||||
noxuDefinition.Spec.Versions[1].Schema = &apiextensionsv1.CustomResourceValidation{
|
||||
OpenAPIV3Schema: schema.DeepCopy(),
|
||||
}
|
||||
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -554,7 +510,7 @@ func TestValidateOnlyStatus(t *testing.T) {
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -576,9 +532,9 @@ func TestSubresourcesDiscovery(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped)
|
||||
for _, noxuDefinition := range noxuDefinitions {
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
||||
}
|
||||
if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
||||
if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -658,9 +614,9 @@ func TestGeneration(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped)
|
||||
for _, noxuDefinition := range noxuDefinitions {
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -718,7 +674,7 @@ func TestGeneration(t *testing.T) {
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -745,9 +701,9 @@ func TestSubresourcePatch(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinitions := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped)
|
||||
for _, noxuDefinition := range noxuDefinitions {
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -882,7 +838,7 @@ func TestSubresourcePatch(t *testing.T) {
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -32,42 +32,42 @@ import (
|
||||
"k8s.io/client-go/dynamic"
|
||||
"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/test/integration/fixtures"
|
||||
)
|
||||
|
||||
func newTableCRD() *apiextensionsv1beta1.CustomResourceDefinition {
|
||||
return &apiextensionsv1beta1.CustomResourceDefinition{
|
||||
func newTableCRD() *apiextensionsv1.CustomResourceDefinition {
|
||||
return &apiextensionsv1.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "tables.mygroup.example.com"},
|
||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||
Group: "mygroup.example.com",
|
||||
Version: "v1beta1",
|
||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||
Group: "mygroup.example.com",
|
||||
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||
Plural: "tables",
|
||||
Singular: "table",
|
||||
Kind: "Table",
|
||||
ListKind: "TablemList",
|
||||
},
|
||||
Scope: apiextensionsv1beta1.ClusterScoped,
|
||||
Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{
|
||||
Scope: apiextensionsv1.ClusterScoped,
|
||||
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "v1beta1",
|
||||
Served: true,
|
||||
Storage: false,
|
||||
AdditionalPrinterColumns: []apiextensionsv1beta1.CustomResourceColumnDefinition{
|
||||
AdditionalPrinterColumns: []apiextensionsv1.CustomResourceColumnDefinition{
|
||||
{Name: "Age", Type: "date", JSONPath: ".metadata.creationTimestamp"},
|
||||
{Name: "Alpha", Type: "string", JSONPath: ".spec.alpha"},
|
||||
{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: "Epsilon", Type: "string", Description: "an array of integers as string", JSONPath: ".spec.epsilon"},
|
||||
},
|
||||
Schema: fixtures.AllowAllSchema(),
|
||||
},
|
||||
{
|
||||
Name: "v1",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
AdditionalPrinterColumns: []apiextensionsv1beta1.CustomResourceColumnDefinition{
|
||||
AdditionalPrinterColumns: []apiextensionsv1.CustomResourceColumnDefinition{
|
||||
{Name: "Age", Type: "date", JSONPath: ".metadata.creationTimestamp"},
|
||||
{Name: "Alpha", Type: "string", JSONPath: ".spec.alpha"},
|
||||
{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: "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, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
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 {
|
||||
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 := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped)[0]
|
||||
crd, err = fixtures.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
crd := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped)[0]
|
||||
crd, err = fixtures.CreateNewV1CustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
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
|
||||
// should not be defaulted during creation, and apiserver should not return validation
|
||||
// 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 {
|
||||
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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -420,11 +457,11 @@ func TestPatchCleanTopLevelColumns(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
crd := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.NamespaceScoped)[0]
|
||||
crd.Spec.AdditionalPrinterColumns = []apiextensionsv1beta1.CustomResourceColumnDefinition{
|
||||
crd := NewNoxuSubresourcesCRDs(apiextensionsv1.NamespaceScoped)[0]
|
||||
crd.Spec.Versions[0].AdditionalPrinterColumns = []apiextensionsv1.CustomResourceColumnDefinition{
|
||||
{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 {
|
||||
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
|
||||
// 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 {
|
||||
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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ package integration
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@ -27,9 +28,10 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"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/yaml"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
|
||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
@ -44,8 +46,8 @@ func TestForProperValidationErrors(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -91,13 +93,11 @@ func TestForProperValidationErrors(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func newNoxuValidationCRDs(scope apiextensionsv1beta1.ResourceScope) []*apiextensionsv1beta1.CustomResourceDefinition {
|
||||
validationSchema := &apiextensionsv1beta1.JSONSchemaProps{
|
||||
func newNoxuValidationCRDs() []*apiextensionsv1.CustomResourceDefinition {
|
||||
validationSchema := &apiextensionsv1.JSONSchemaProps{
|
||||
Type: "object",
|
||||
Required: []string{"alpha", "beta"},
|
||||
AdditionalProperties: &apiextensionsv1beta1.JSONSchemaPropsOrBool{
|
||||
Allows: true,
|
||||
},
|
||||
Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
|
||||
Properties: map[string]apiextensionsv1.JSONSchemaProps{
|
||||
"alpha": {
|
||||
Description: "Alpha is an alphanumeric string with underscores",
|
||||
Type: "string",
|
||||
@ -111,7 +111,7 @@ func newNoxuValidationCRDs(scope apiextensionsv1beta1.ResourceScope) []*apiexten
|
||||
"gamma": {
|
||||
Description: "Gamma is restricted to foo, bar and baz",
|
||||
Type: "string",
|
||||
Enum: []apiextensionsv1beta1.JSON{
|
||||
Enum: []apiextensionsv1.JSON{
|
||||
{
|
||||
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.Description = "test"
|
||||
return []*apiextensionsv1beta1.CustomResourceDefinition{
|
||||
return []*apiextensionsv1.CustomResourceDefinition{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"},
|
||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||
Group: "mygroup.example.com",
|
||||
Version: "v1beta1",
|
||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||
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: apiextensionsv1beta1.NamespaceScoped,
|
||||
Validation: &apiextensionsv1beta1.CustomResourceValidation{
|
||||
OpenAPIV3Schema: validationSchema,
|
||||
},
|
||||
Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{
|
||||
Scope: apiextensionsv1.NamespaceScoped,
|
||||
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "v1beta1",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
},
|
||||
{
|
||||
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{
|
||||
Schema: &apiextensionsv1.CustomResourceValidation{
|
||||
OpenAPIV3Schema: validationSchema,
|
||||
},
|
||||
},
|
||||
@ -197,7 +153,39 @@ func newNoxuValidationCRDs(scope apiextensionsv1beta1.ResourceScope) []*apiexten
|
||||
Name: "v1",
|
||||
Served: true,
|
||||
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,
|
||||
},
|
||||
},
|
||||
@ -231,9 +219,9 @@ func TestCustomResourceValidation(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinitions := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinitions := newNoxuValidationCRDs()
|
||||
for _, noxuDefinition := range noxuDefinitions {
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -249,7 +237,7 @@ func TestCustomResourceValidation(t *testing.T) {
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -436,9 +424,9 @@ func TestCustomResourceUpdateValidation(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinitions := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinitions := newNoxuValidationCRDs()
|
||||
for _, noxuDefinition := range noxuDefinitions {
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -476,7 +464,7 @@ func TestCustomResourceUpdateValidation(t *testing.T) {
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -489,9 +477,9 @@ func TestCustomResourceValidationErrors(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinitions := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinitions := newNoxuValidationCRDs()
|
||||
for _, noxuDefinition := range noxuDefinitions {
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -530,18 +518,6 @@ func TestCustomResourceValidationErrors(t *testing.T) {
|
||||
},
|
||||
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",
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -593,26 +569,27 @@ func TestCRValidationOnCRDUpdate(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinitions := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinitions := newNoxuValidationCRDs()
|
||||
for i, noxuDefinition := range noxuDefinitions {
|
||||
for _, v := range noxuDefinition.Spec.Versions {
|
||||
// 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)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ns := "not-the-default"
|
||||
noxuResourceClient := newNamespacedCustomResourceVersionedClient(ns, dynamicClient, noxuDefinition, v.Name)
|
||||
instanceToCreate := newNoxuValidationInstance(ns, "foo")
|
||||
unstructured.RemoveNestedField(instanceToCreate.Object, "gamma")
|
||||
instanceToCreate.Object["apiVersion"] = fmt.Sprintf("%s/%s", noxuDefinition.Spec.Group, v.Name)
|
||||
|
||||
// CR is rejected
|
||||
@ -622,7 +599,7 @@ func TestCRValidationOnCRDUpdate(t *testing.T) {
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -650,7 +627,7 @@ func TestCRValidationOnCRDUpdate(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -664,51 +641,59 @@ func TestForbiddenFieldsInSchema(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinitions := newNoxuValidationCRDs(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinitions := newNoxuValidationCRDs()
|
||||
for i, noxuDefinition := range noxuDefinitions {
|
||||
for _, v := range noxuDefinition.Spec.Versions {
|
||||
// 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)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
validationSchema.OpenAPIV3Schema.AdditionalProperties.Allows = false
|
||||
|
||||
_, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
existingProperties := validationSchema.OpenAPIV3Schema.Properties
|
||||
validationSchema.OpenAPIV3Schema.Properties = nil
|
||||
validationSchema.OpenAPIV3Schema.AdditionalProperties = &apiextensionsv1.JSONSchemaPropsOrBool{Allows: false}
|
||||
_, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err == nil {
|
||||
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",
|
||||
UniqueItems: true,
|
||||
AdditionalProperties: &apiextensionsv1.JSONSchemaPropsOrBool{
|
||||
Allows: true,
|
||||
},
|
||||
}
|
||||
validationSchema.OpenAPIV3Schema.AdditionalProperties.Allows = true
|
||||
|
||||
_, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
_, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err == nil {
|
||||
t.Fatalf("unexpected non-error: uniqueItems cannot be set to true")
|
||||
}
|
||||
|
||||
validationSchema.OpenAPIV3Schema.Ref = strPtr("#/definition/zeta")
|
||||
validationSchema.OpenAPIV3Schema.Properties["zeta"] = apiextensionsv1beta1.JSONSchemaProps{
|
||||
validationSchema.OpenAPIV3Schema.Properties["zeta"] = apiextensionsv1.JSONSchemaProps{
|
||||
Type: "array",
|
||||
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 {
|
||||
t.Fatal("unexpected non-error: $ref cannot be non-empty string")
|
||||
}
|
||||
|
||||
validationSchema.OpenAPIV3Schema.Ref = nil
|
||||
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := fixtures.DeleteCustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
||||
if err := fixtures.DeleteV1CustomResourceDefinition(noxuDefinition, apiExtensionClient); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -716,7 +701,7 @@ func TestForbiddenFieldsInSchema(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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -752,27 +737,37 @@ spec:
|
||||
if err != nil {
|
||||
t.Fatalf("failed decoding of: %v\n\n%s", err, manifest)
|
||||
}
|
||||
crd := obj.(*apiextensionsv1beta1.CustomResourceDefinition)
|
||||
name := crd.Name
|
||||
betaCRD := obj.(*apiextensionsv1beta1.CustomResourceDefinition)
|
||||
name := betaCRD.Name
|
||||
|
||||
// save schema for later
|
||||
origSchema := crd.Spec.Validation.OpenAPIV3Schema
|
||||
origSchema := &apiextensionsv1.JSONSchemaProps{
|
||||
Type: "object",
|
||||
Properties: map[string]apiextensionsv1.JSONSchemaProps{
|
||||
"a": {
|
||||
Type: "object",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// create CRDs
|
||||
t.Logf("Creating CRD %s", crd.Name)
|
||||
if _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Create(context.TODO(), crd, metav1.CreateOptions{}); err != nil {
|
||||
t.Fatalf("unexpected create error: %v", err)
|
||||
// create CRDs. We cannot create these in v1, but they can exist in upgraded clusters
|
||||
t.Logf("Creating CRD %s", betaCRD.Name)
|
||||
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceNone)
|
||||
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
|
||||
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) {
|
||||
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 {
|
||||
return false, err
|
||||
}
|
||||
cond = findCRDCondition(obj, apiextensionsv1beta1.NonStructuralSchema)
|
||||
cond = findCRDCondition(obj, apiextensionsv1.NonStructuralSchema)
|
||||
return cond != nil, nil
|
||||
})
|
||||
if err != nil {
|
||||
@ -785,34 +780,32 @@ spec:
|
||||
t.Fatalf("expected violation %q, but got: %v", v, cond.Message)
|
||||
}
|
||||
|
||||
// remove schema
|
||||
t.Log("Remove schema")
|
||||
t.Log("fix schema")
|
||||
for retry := 0; retry < 5; retry++ {
|
||||
// This patch fixes two fields to resolve
|
||||
// 1. property type validation error
|
||||
// 2. preserveUnknownFields validation error
|
||||
patch := []byte("[{\"op\":\"add\",\"path\":\"/spec/validation/openAPIV3Schema/properties/a/type\",\"value\":\"int\"}," +
|
||||
"{\"op\":\"replace\",\"path\":\"/spec/preserveUnknownFields\",\"value\":false}]")
|
||||
if _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Patch(context.TODO(), name, types.JSONPatchType, patch, metav1.PatchOptions{}); apierrors.IsConflict(err) {
|
||||
crd, err := apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.TODO(), name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
crd.Spec.Versions[0].Schema = fixtures.AllowAllSchema()
|
||||
crd.Spec.PreserveUnknownFields = false
|
||||
_, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{})
|
||||
if apierrors.IsConflict(err) {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected update error: %v", err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected update error: %v", err)
|
||||
}
|
||||
|
||||
// wait for condition to go away
|
||||
t.Log("Wait for condition to disappear")
|
||||
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 {
|
||||
return false, err
|
||||
}
|
||||
cond = findCRDCondition(obj, apiextensionsv1beta1.NonStructuralSchema)
|
||||
cond = findCRDCondition(obj, apiextensionsv1.NonStructuralSchema)
|
||||
return cond == nil, nil
|
||||
})
|
||||
if err != nil {
|
||||
@ -822,43 +815,23 @@ spec:
|
||||
// re-add schema
|
||||
t.Log("Re-add schema")
|
||||
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 {
|
||||
t.Fatalf("unexpected get error: %v", err)
|
||||
}
|
||||
crd.Spec.PreserveUnknownFields = nil
|
||||
crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{OpenAPIV3Schema: origSchema}
|
||||
if _, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}); apierrors.IsConflict(err) {
|
||||
crd.Spec.PreserveUnknownFields = true
|
||||
crd.Spec.Versions[0].Schema = &apiextensionsv1.CustomResourceValidation{OpenAPIV3Schema: origSchema}
|
||||
if _, err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Update(context.TODO(), crd, metav1.UpdateOptions{}); apierrors.IsConflict(err) {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected update error: %v", err)
|
||||
if err == nil {
|
||||
t.Fatalf("missing error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "spec.preserveUnknownFields") {
|
||||
t.Fatal(err)
|
||||
}
|
||||
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) {
|
||||
@ -1657,13 +1630,13 @@ properties:
|
||||
|
||||
if len(tst.expectedViolations) == 0 {
|
||||
// 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) {
|
||||
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 {
|
||||
return false, err
|
||||
}
|
||||
cond = findCRDCondition(obj, apiextensionsv1beta1.NonStructuralSchema)
|
||||
cond = findCRDCondition(obj, apiextensionsv1.NonStructuralSchema)
|
||||
if cond == nil {
|
||||
return false, nil
|
||||
}
|
||||
@ -1676,13 +1649,13 @@ properties:
|
||||
}
|
||||
|
||||
// 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) {
|
||||
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 {
|
||||
return false, err
|
||||
}
|
||||
cond = findCRDCondition(obj, apiextensionsv1beta1.NonStructuralSchema)
|
||||
cond = findCRDCondition(obj, apiextensionsv1.NonStructuralSchema)
|
||||
if cond != nil {
|
||||
return true, nil
|
||||
}
|
||||
@ -1696,7 +1669,7 @@ properties:
|
||||
if cond.Reason != "Violations" {
|
||||
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)
|
||||
}
|
||||
|
||||
@ -1717,7 +1690,7 @@ properties:
|
||||
}
|
||||
|
||||
// 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 {
|
||||
if crd.Status.Conditions[i].Type == conditionType {
|
||||
return &crd.Status.Conditions[i]
|
||||
@ -1742,10 +1715,6 @@ func float64Ptr(f float64) *float64 {
|
||||
return &f
|
||||
}
|
||||
|
||||
func int64Ptr(f int64) *int64 {
|
||||
return &f
|
||||
}
|
||||
|
||||
func strPtr(str string) *string {
|
||||
return &str
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ import (
|
||||
"time"
|
||||
|
||||
"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/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@ -40,13 +40,13 @@ func TestInternalVersionIsHandlerVersion(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1.NamespaceScoped)
|
||||
|
||||
assert.Equal(t, "v1beta1", noxuDefinition.Spec.Versions[0].Name)
|
||||
assert.Equal(t, "v1beta2", noxuDefinition.Spec.Versions[1].Name)
|
||||
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 {
|
||||
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
|
||||
t.Logf("Updating CRD to validate apiVersion")
|
||||
noxuDefinition, err = UpdateCustomResourceDefinitionWithRetry(apiExtensionClient, noxuDefinition.Name, func(crd *apiextensionsv1beta1.CustomResourceDefinition) {
|
||||
crd.Spec.Validation = &apiextensionsv1beta1.CustomResourceValidation{
|
||||
OpenAPIV3Schema: &apiextensionsv1beta1.JSONSchemaProps{
|
||||
Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
|
||||
"apiVersion": {
|
||||
Pattern: "^mygroup.example.com/v1beta1$", // this means we can only patch via the v1beta1 handler version
|
||||
noxuDefinition, err = UpdateCustomResourceDefinitionWithRetry(apiExtensionClient, noxuDefinition.Name, func(crd *apiextensionsv1.CustomResourceDefinition) {
|
||||
for i := range crd.Spec.Versions {
|
||||
crd.Spec.Versions[i].Schema = &apiextensionsv1.CustomResourceValidation{
|
||||
OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{
|
||||
Type: "object",
|
||||
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)
|
||||
@ -134,8 +138,8 @@ func TestVersionedNamespacedScopedCRD(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1.NamespaceScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -151,8 +155,8 @@ func TestVersionedClusterScopedCRD(t *testing.T) {
|
||||
}
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -162,40 +166,44 @@ func TestVersionedClusterScopedCRD(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestStoragedVersionInNamespacedCRDStatus(t *testing.T) {
|
||||
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.NamespaceScoped)
|
||||
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1.NamespaceScoped)
|
||||
ns := "not-the-default"
|
||||
testStoragedVersionInCRDStatus(t, ns, noxuDefinition)
|
||||
}
|
||||
|
||||
func TestStoragedVersionInClusterScopedCRDStatus(t *testing.T) {
|
||||
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1beta1.ClusterScoped)
|
||||
noxuDefinition := fixtures.NewMultipleVersionNoxuCRD(apiextensionsv1.ClusterScoped)
|
||||
ns := ""
|
||||
testStoragedVersionInCRDStatus(t, ns, noxuDefinition)
|
||||
}
|
||||
|
||||
func testStoragedVersionInCRDStatus(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition) {
|
||||
versionsV1Beta1Storage := []apiextensionsv1beta1.CustomResourceDefinitionVersion{
|
||||
func testStoragedVersionInCRDStatus(t *testing.T, ns string, noxuDefinition *apiextensionsv1.CustomResourceDefinition) {
|
||||
versionsV1Beta1Storage := []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "v1beta1",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
Schema: fixtures.AllowAllSchema(),
|
||||
},
|
||||
{
|
||||
Name: "v1beta2",
|
||||
Served: true,
|
||||
Storage: false,
|
||||
Schema: fixtures.AllowAllSchema(),
|
||||
},
|
||||
}
|
||||
versionsV1Beta2Storage := []apiextensionsv1beta1.CustomResourceDefinitionVersion{
|
||||
versionsV1Beta2Storage := []apiextensionsv1.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "v1beta1",
|
||||
Served: true,
|
||||
Storage: false,
|
||||
Schema: fixtures.AllowAllSchema(),
|
||||
},
|
||||
{
|
||||
Name: "v1beta2",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
Schema: fixtures.AllowAllSchema(),
|
||||
},
|
||||
}
|
||||
tearDown, apiExtensionClient, dynamicClient, err := fixtures.StartDefaultServerWithClients(t)
|
||||
@ -205,13 +213,13 @@ func testStoragedVersionInCRDStatus(t *testing.T, ns string, noxuDefinition *api
|
||||
defer tearDown()
|
||||
|
||||
noxuDefinition.Spec.Versions = versionsV1Beta1Storage
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -221,11 +229,11 @@ func testStoragedVersionInCRDStatus(t *testing.T, ns string, noxuDefinition *api
|
||||
|
||||
// Changing CRD storage version should be reflected immediately
|
||||
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 {
|
||||
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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -233,7 +241,7 @@ func testStoragedVersionInCRDStatus(t *testing.T, ns string, noxuDefinition *api
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
err = fixtures.DeleteCustomResourceDefinition(crd, apiExtensionClient)
|
||||
err = fixtures.DeleteV1CustomResourceDefinition(crd, apiExtensionClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"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/test/integration/fixtures"
|
||||
)
|
||||
@ -51,15 +51,15 @@ func TestYAML(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
noxuDefinition := fixtures.NewNoxuCustomResourceDefinition(apiextensionsv1beta1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := fixtures.NewNoxuV1CustomResourceDefinition(apiextensionsv1.ClusterScoped)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
kind := noxuDefinition.Spec.Names.Kind
|
||||
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()
|
||||
|
||||
@ -67,7 +67,7 @@ func TestYAML(t *testing.T) {
|
||||
{
|
||||
result, err := rest.Get().
|
||||
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())
|
||||
if err != nil {
|
||||
t.Fatal(err, string(result))
|
||||
@ -88,7 +88,7 @@ func TestYAML(t *testing.T) {
|
||||
{
|
||||
result, err := rest.Get().
|
||||
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())
|
||||
if !errors.IsNotFound(err) {
|
||||
t.Fatalf("expected not found, got %v", err)
|
||||
@ -123,7 +123,7 @@ values:
|
||||
result, err := rest.Post().
|
||||
SetHeader("Accept", "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).
|
||||
DoRaw(context.TODO())
|
||||
if err != nil {
|
||||
@ -159,7 +159,7 @@ values:
|
||||
{
|
||||
result, err := rest.Get().
|
||||
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())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -192,7 +192,7 @@ values:
|
||||
{
|
||||
result, err := rest.Get().
|
||||
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())
|
||||
if err != nil {
|
||||
t.Fatal(err, string(result))
|
||||
@ -236,7 +236,7 @@ values:
|
||||
{
|
||||
result, err := rest.Get().
|
||||
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").
|
||||
DoRaw(context.TODO())
|
||||
if !errors.IsNotAcceptable(err) {
|
||||
@ -273,7 +273,7 @@ values:
|
||||
result, err := rest.Put().
|
||||
SetHeader("Accept", "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).
|
||||
DoRaw(context.TODO())
|
||||
if err != nil {
|
||||
@ -314,7 +314,7 @@ values:
|
||||
result, err := rest.Patch(types.MergePatchType).
|
||||
SetHeader("Accept", "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).
|
||||
DoRaw(context.TODO())
|
||||
if !errors.IsUnsupportedMediaType(err) {
|
||||
@ -336,7 +336,7 @@ values:
|
||||
{
|
||||
result, err := rest.Delete().
|
||||
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())
|
||||
if err != nil {
|
||||
t.Fatal(err, string(result))
|
||||
@ -370,14 +370,14 @@ func TestYAMLSubresource(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
noxuDefinition := NewNoxuSubresourcesCRDs(apiextensionsv1beta1.ClusterScoped)[0]
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition := NewNoxuSubresourcesCRDs(apiextensionsv1.ClusterScoped)[0]
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
@ -397,7 +397,7 @@ spec:
|
||||
result, err := rest.Post().
|
||||
SetHeader("Accept", "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).
|
||||
DoRaw(context.TODO())
|
||||
if err != nil {
|
||||
@ -427,7 +427,7 @@ spec:
|
||||
{
|
||||
result, err := rest.Get().
|
||||
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())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -466,7 +466,7 @@ status:
|
||||
result, err := rest.Put().
|
||||
SetHeader("Accept", "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).
|
||||
DoRaw(context.TODO())
|
||||
if err != nil {
|
||||
@ -500,7 +500,7 @@ status:
|
||||
{
|
||||
result, err := rest.Get().
|
||||
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())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -34,7 +34,7 @@ import (
|
||||
|
||||
apps "k8s.io/api/apps/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"
|
||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
@ -798,28 +798,35 @@ func TestMetadataClient(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fooCRD := &apiextensionsv1beta1.CustomResourceDefinition{
|
||||
fooCRD := &apiextensionsv1.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foos.cr.bar.com",
|
||||
},
|
||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||
Group: "cr.bar.com",
|
||||
Version: "v1",
|
||||
Scope: apiextensionsv1beta1.NamespaceScoped,
|
||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||
Group: "cr.bar.com",
|
||||
Scope: apiextensionsv1.NamespaceScoped,
|
||||
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||
Plural: "foos",
|
||||
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 {
|
||||
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 {
|
||||
name string
|
||||
@ -1119,26 +1126,33 @@ func TestAPICRDProtobuf(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fooCRD := &apiextensionsv1beta1.CustomResourceDefinition{
|
||||
fooCRD := &apiextensionsv1.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foos.cr.bar.com",
|
||||
},
|
||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||
Group: "cr.bar.com",
|
||||
Version: "v1",
|
||||
Scope: apiextensionsv1beta1.NamespaceScoped,
|
||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||
Group: "cr.bar.com",
|
||||
Scope: apiextensionsv1.NamespaceScoped,
|
||||
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||
Plural: "foos",
|
||||
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 {
|
||||
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)
|
||||
|
||||
testcases := []struct {
|
||||
@ -1331,25 +1345,32 @@ func TestTransform(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fooCRD := &apiextensionsv1beta1.CustomResourceDefinition{
|
||||
fooCRD := &apiextensionsv1.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foos.cr.bar.com",
|
||||
},
|
||||
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||
Group: "cr.bar.com",
|
||||
Version: "v1",
|
||||
Scope: apiextensionsv1beta1.NamespaceScoped,
|
||||
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||
Group: "cr.bar.com",
|
||||
Scope: apiextensionsv1.NamespaceScoped,
|
||||
Names: apiextensionsv1.CustomResourceDefinitionNames{
|
||||
Plural: "foos",
|
||||
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 {
|
||||
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)
|
||||
|
||||
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"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"path"
|
||||
"reflect"
|
||||
"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"
|
||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
@ -39,163 +49,6 @@ import (
|
||||
"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,
|
||||
// it will be used to construct the CR schema used by apply.
|
||||
func TestApplyCRDStructuralSchema(t *testing.T) {
|
||||
@ -217,9 +70,9 @@ func TestApplyCRDStructuralSchema(t *testing.T) {
|
||||
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(`{
|
||||
"openAPIV3Schema": {
|
||||
"type": "object",
|
||||
@ -274,17 +127,17 @@ func TestApplyCRDStructuralSchema(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
noxuDefinition.Spec.Validation = &c
|
||||
falseBool := false
|
||||
noxuDefinition.Spec.PreserveUnknownFields = &falseBool
|
||||
for i := range noxuDefinition.Spec.Versions {
|
||||
noxuDefinition.Spec.Versions[i].Schema = &c
|
||||
}
|
||||
|
||||
noxuDefinition, err = fixtures.CreateNewCustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
noxuDefinition, err = fixtures.CreateNewV1CustomResourceDefinition(noxuDefinition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
kind := noxuDefinition.Spec.Names.Kind
|
||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Version
|
||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name
|
||||
name := "mytest"
|
||||
|
||||
rest := apiExtensionClient.Discovery().RESTClient()
|
||||
@ -303,7 +156,7 @@ spec:
|
||||
containerPort: 80
|
||||
protocol: TCP`, apiVersion, kind, name))
|
||||
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).
|
||||
Param("fieldManager", "apply_test").
|
||||
Body(yamlBody).
|
||||
@ -318,7 +171,7 @@ spec:
|
||||
|
||||
// Patch object to add another finalizer to the finalizers list
|
||||
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).
|
||||
Body([]byte(`{"metadata":{"finalizers":["test-finalizer","another-one"]}}`)).
|
||||
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'.
|
||||
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).
|
||||
Param("fieldManager", "apply_test").
|
||||
SetHeader("Accept", "application/json").
|
||||
@ -346,7 +199,7 @@ spec:
|
||||
|
||||
// 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).
|
||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||
Name(name).
|
||||
Body([]byte(`{"spec":{"replicas": 5}}`)).
|
||||
DoRaw(context.TODO())
|
||||
@ -357,7 +210,7 @@ spec:
|
||||
|
||||
// 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).
|
||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||
Name(name).
|
||||
Param("fieldManager", "apply_test").
|
||||
Body(yamlBody).
|
||||
@ -375,7 +228,7 @@ spec:
|
||||
|
||||
// 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).
|
||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||
Name(name).
|
||||
Param("force", "true").
|
||||
Param("fieldManager", "apply_test").
|
||||
@ -388,7 +241,7 @@ spec:
|
||||
|
||||
// New applier tries to edit an existing list item, we should get conflicts.
|
||||
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).
|
||||
Param("fieldManager", "apply_test_2").
|
||||
Body([]byte(fmt.Sprintf(`
|
||||
@ -415,7 +268,7 @@ spec:
|
||||
|
||||
// New applier tries to add a new list item, should work fine.
|
||||
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).
|
||||
Param("fieldManager", "apply_test_2").
|
||||
Body([]byte(fmt.Sprintf(`
|
||||
@ -459,7 +312,7 @@ spec:
|
||||
"protocol": "TCP"
|
||||
}`, apiVersion, kind, "should-not-exist"))
|
||||
_, 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").
|
||||
Param("fieldManager", "apply_test").
|
||||
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,
|
||||
// apply falls back to non-schema behavior
|
||||
func TestApplyCRDUnhandledSchema(t *testing.T) {
|
||||
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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -568,12 +454,33 @@ func TestApplyCRDUnhandledSchema(t *testing.T) {
|
||||
if err != nil {
|
||||
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.
|
||||
// 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 {
|
||||
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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
kind := noxuDefinition.Spec.Names.Kind
|
||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Version
|
||||
apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name
|
||||
name := "mytest"
|
||||
|
||||
rest := apiExtensionClient.Discovery().RESTClient()
|
||||
@ -610,7 +546,7 @@ metadata:
|
||||
spec:
|
||||
replicas: 1`, apiVersion, kind, name))
|
||||
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).
|
||||
Param("fieldManager", "apply_test").
|
||||
Body(yamlBody).
|
||||
@ -622,7 +558,7 @@ spec:
|
||||
|
||||
// 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).
|
||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||
Name(name).
|
||||
Body([]byte(`{"spec":{"replicas": 5}}`)).
|
||||
DoRaw(context.TODO())
|
||||
@ -633,7 +569,7 @@ spec:
|
||||
|
||||
// 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).
|
||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||
Name(name).
|
||||
Param("fieldManager", "apply_test").
|
||||
Body(yamlBody).
|
||||
@ -651,7 +587,7 @@ spec:
|
||||
|
||||
// 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).
|
||||
AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
|
||||
Name(name).
|
||||
Param("force", "true").
|
||||
Param("fieldManager", "apply_test").
|
||||
|
@ -26,7 +26,7 @@ import (
|
||||
"time"
|
||||
|
||||
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"
|
||||
apiextensionstestserver "k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||
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{
|
||||
Object: map[string]interface{}{
|
||||
"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{}{
|
||||
"name": name,
|
||||
"namespace": namespace,
|
||||
@ -180,18 +180,18 @@ func createRandomCustomResourceDefinition(
|
||||
t *testing.T, apiExtensionClient apiextensionsclientset.Interface,
|
||||
dynamicClient dynamic.Interface,
|
||||
namespace string,
|
||||
) (*apiextensionsv1beta1.CustomResourceDefinition, dynamic.ResourceInterface) {
|
||||
) (*apiextensionsv1.CustomResourceDefinition, dynamic.ResourceInterface) {
|
||||
// Create a random custom resource definition and ensure it's available for
|
||||
// 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 {
|
||||
t.Fatalf("failed to create CustomResourceDefinition: %v", err)
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
@ -1230,14 +1230,14 @@ func TestCRDDeletionCascading(t *testing.T) {
|
||||
t.Logf("Second pass CRD cascading deletion")
|
||||
accessor := meta.NewAccessor()
|
||||
accessor.SetResourceVersion(definition, "")
|
||||
_, err := apiextensionstestserver.CreateNewCustomResourceDefinition(definition, apiExtensionClient, dynamicClient)
|
||||
_, err := apiextensionstestserver.CreateNewV1CustomResourceDefinition(definition, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create CustomResourceDefinition: %v", err)
|
||||
}
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
|
@ -89,12 +89,7 @@ func CreateMultiVersionTestCRD(f *framework.Framework, group string, opts ...Opt
|
||||
Served: true,
|
||||
Storage: true,
|
||||
Name: "v1",
|
||||
Schema: &apiextensionsv1.CustomResourceValidation{
|
||||
OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{
|
||||
XPreserveUnknownFields: pointer.BoolPtr(true),
|
||||
Type: "object",
|
||||
},
|
||||
},
|
||||
Schema: fixtures.AllowAllSchema(),
|
||||
}}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user