package console
import (
"encoding/json"
"io"
"net/http"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
var _ = Describe("CustomResourceDefinition 资源接口测试", Label("with-workload-cluster"), func() {
Context("CustomResourceDefinition 创建", func() {
It("创建成功", func() {
resp, err := createCustomResourceDefinition("TestCrdSuccess")
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusCreated), string(body))
defer func() {
_, err := makeRequest("DELETE", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrdsuccesss.example.com", nil)
Expect(err).NotTo(HaveOccurred())
}()
})
It("创建失败 - 字段有误", func() {
crdYAML := map[string]interface{}{
"apiVersion": "apiextensions.k8s.io/v1",
"kind": "CustomResourceDefinition",
"metadata": map[string]interface{}{
"name": "test-crd-invalids.example.com",
},
"spec": map[string]interface{}{
"group": "example.com",
"versions": []map[string]interface{}{
{
"name": "v1",
"served": true,
"storage": true,
"schema": map[string]interface{}{
"openAPIV3Schema": map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"spec": map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"replicas": map[string]interface{}{
"type": "integer",
},
},
},
},
},
},
},
},
"scope": "Namespaced",
"names": map[string]interface{}{
"plural": "testcrdinvalids",
"singular": "testcrdinvalid",
"kind": "TestCRDInvalid",
},
},
}
resp, err := makeRequest("POST", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions", crdYAML)
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusUnprocessableEntity), string(body))
})
It("创建失败 - 已存在同名", func() {
resp1, err := createCustomResourceDefinition("TestCrdExisting")
Expect(err).NotTo(HaveOccurred())
defer resp1.Body.Close()
Expect(resp1.StatusCode).To(Equal(http.StatusCreated))
defer func() {
_, err := makeRequest("DELETE", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrdexistings.example.com", nil)
Expect(err).NotTo(HaveOccurred())
}()
resp2, err := createCustomResourceDefinition("TestCrdExisting")
Expect(err).NotTo(HaveOccurred())
defer resp2.Body.Close()
body, err := io.ReadAll(resp2.Body)
Expect(err).NotTo(HaveOccurred())
Expect(resp2.StatusCode).To(Equal(http.StatusConflict), string(body))
})
})
Context("CustomResourceDefinition 查询", func() {
It("查询成功", func() {
_, err := createCustomResourceDefinition("TestCrdQuery")
Expect(err).NotTo(HaveOccurred())
defer func() {
_, err := makeRequest("DELETE", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrdquerys.example.com", nil)
Expect(err).NotTo(HaveOccurred())
}()
resp, err := makeRequest("GET", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrdquerys.example.com", nil)
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusOK), string(body))
var crd map[string]interface{}
err = json.Unmarshal(body, &crd)
Expect(err).NotTo(HaveOccurred())
Expect(crd["metadata"].(map[string]interface{})["name"]).To(Equal("testcrdquerys.example.com"))
})
})
Context("CustomResourceDefinition 修改", func() {
It("修改成功", func() {
_, err := createCustomResourceDefinition("TestCrdUpdateSuccess")
Expect(err).NotTo(HaveOccurred())
defer func() {
_, err := makeRequest("DELETE", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrdupdatesuccesss.example.com", nil)
Expect(err).NotTo(HaveOccurred())
}()
patchCRD := map[string]interface{}{
"metadata": map[string]interface{}{
"name": "testcrdupdatesuccesss.example.com",
"labels": map[string]interface{}{
"app": "test",
},
"annotations": map[string]interface{}{
"app": "test",
},
},
}
resp, err := makeRequest("PATCH", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrdupdatesuccesss.example.com", patchCRD)
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusOK), string(body))
})
It("修改失败 - 字段有误", func() {
_, err := createCustomResourceDefinition("TestCrdInvalidUpdate")
Expect(err).NotTo(HaveOccurred())
defer func() {
_, err := makeRequest("DELETE", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrdinvalidupdates.example.com", nil)
Expect(err).NotTo(HaveOccurred())
}()
patch := createMalformedPatch("TestCrdInvalidUpdate", "")
resp, err := makeRequest("PATCH", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrdinvalidupdates.example.com", patch)
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusUnprocessableEntity), string(body))
})
It("修改其他同类资源", func() {
_, err := createCustomResourceDefinition("TestCrdOtherResource")
Expect(err).NotTo(HaveOccurred())
_, err = createCustomResourceDefinition("OtherCrd")
Expect(err).NotTo(HaveOccurred())
defer func() {
_, err := makeRequest("DELETE", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrdotherresources.example.com", nil)
Expect(err).NotTo(HaveOccurred())
_, err = makeRequest("DELETE", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/othercrds.example.com", nil)
Expect(err).NotTo(HaveOccurred())
}()
patch := createPatch("other-cr", "")
resp, err := makeRequest("PATCH", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrdotherresources.example.com", patch)
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusBadRequest), string(body))
})
})
Context("CustomResourceDefinition 删除", func() {
It("删除成功", func() {
_, err := createCustomResourceDefinition("TestCrdDelete")
Expect(err).NotTo(HaveOccurred())
defer func() {
_, err := makeRequest("DELETE", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrddeletes.example.com", nil)
Expect(err).NotTo(HaveOccurred())
}()
resp, err := makeRequest("DELETE", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrddeletes.example.com", nil)
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusOK), string(body))
})
})
})
var _ = Describe("CustomResource 资源接口测试", Label("with-workload-cluster"), func() {
Context("CustomResource 创建", func() {
It("创建成功", func() {
_, err := createCustomResourceDefinition("TestCrdSuccess")
Expect(err).NotTo(HaveOccurred())
resp, err := createCustomResource("test-cr-success", "default", "TestCrdSuccess")
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusCreated), string(body))
defer func() {
_, err := makeRequest("DELETE", "/apis/example.com/v1/namespaces/default/testcrdsuccesss/test-cr-success", nil)
Expect(err).NotTo(HaveOccurred())
_, err = makeRequest("DELETE", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrdsuccesss.example.com", nil)
Expect(err).NotTo(HaveOccurred())
}()
})
It("创建失败 - 字段有误", func() {
_, err := createCustomResourceDefinition("TestCrdInvalid")
Expect(err).NotTo(HaveOccurred())
defer func() {
_, err := makeRequest("DELETE", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrdinvalids.example.com", nil)
Expect(err).NotTo(HaveOccurred())
}()
crYAML := map[string]interface{}{
"apiVersion": "example.com/v1",
"kind": "TestCrdInvalid",
"metadata": map[string]interface{}{
"name": "test-cr-invalid",
"namespace": "default",
},
"spec": map[string]interface{}{
"targets": []map[string]interface{}{
{
"name": "test-target",
"port": -1,
},
},
},
}
resp, err := makeRequest("POST", "/apis/example.com/v1/namespaces/default/testcrdinvalids", crYAML)
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusUnprocessableEntity), string(body))
})
It("创建失败 - 已存在同名", func() {
_, err := createCustomResourceDefinition("TestCrdExisting")
Expect(err).NotTo(HaveOccurred())
resp1, err := createCustomResource("test-cr-existing", "default", "TestCrdExisting")
Expect(err).NotTo(HaveOccurred())
defer resp1.Body.Close()
Expect(resp1.StatusCode).To(Equal(http.StatusCreated))
defer func() {
_, err := makeRequest("DELETE", "/apis/example.com/v1/namespaces/default/testcrdexisting/test-cr-existing", nil)
Expect(err).NotTo(HaveOccurred())
_, err = makeRequest("DELETE", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrdexistings.example.com", nil)
Expect(err).NotTo(HaveOccurred())
}()
resp2, err := createCustomResource("test-cr-existing", "default", "TestCrdExisting")
Expect(err).NotTo(HaveOccurred())
defer resp2.Body.Close()
body, err := io.ReadAll(resp2.Body)
Expect(err).NotTo(HaveOccurred())
Expect(resp2.StatusCode).To(Equal(http.StatusConflict), string(body))
})
It("创建失败 - Namespace 不存在", func() {
_, err := createCustomResourceDefinition("TestCrdNonExistentNamespace")
Expect(err).NotTo(HaveOccurred())
defer func() {
_, err := makeRequest("DELETE", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrdnonexistentnamespaces.example.com", nil)
Expect(err).NotTo(HaveOccurred())
}()
resp, err := createCustomResource("test-cr-nonexistent-namespace", "nonexistent-namespace", "TestCrdNonExistentNamespace")
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusNotFound), string(body))
})
})
Context("CustomResource 查询", func() {
It("查询成功", func() {
_, err := createCustomResourceDefinition("TestCrdQuery")
Expect(err).NotTo(HaveOccurred())
defer func() {
_, err := makeRequest("DELETE", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrdquerys.example.com", nil)
Expect(err).NotTo(HaveOccurred())
}()
_, err = createCustomResource("test-cr-query", "default", "TestCrdQuery")
Expect(err).NotTo(HaveOccurred())
resp, err := makeRequest("GET", "/apis/example.com/v1/namespaces/default/testcrdquerys/test-cr-query", nil)
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusOK), string(body))
var cr map[string]interface{}
err = json.Unmarshal(body, &cr)
Expect(err).NotTo(HaveOccurred())
Expect(cr["metadata"].(map[string]interface{})["name"]).To(Equal("test-cr-query"))
})
})
Context("CustomResource 修改", func() {
It("修改成功", func() {
_, err := createCustomResourceDefinition("TestCrdUpdateSuccess")
Expect(err).NotTo(HaveOccurred())
_, err = createCustomResource("test-cr-update-success", "default", "TestCrdUpdateSuccess")
Expect(err).NotTo(HaveOccurred())
defer func() {
_, err := makeRequest("DELETE", "/apis/example.com/v1/namespaces/default/testcrdupdatesuccesss/test-cr-update-success", nil)
Expect(err).NotTo(HaveOccurred())
_, err = makeRequest("DELETE", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrdupdatesuccesss.example.com", nil)
Expect(err).NotTo(HaveOccurred())
}()
patch := createPatch("test-cr-update-success", "default")
resp, err := makeRequest("PATCH", "/apis/example.com/v1/namespaces/default/testcrdupdatesuccesss/test-cr-update-success", patch)
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusOK), string(body))
})
It("修改失败 - 字段有误", func() {
_, err := createCustomResourceDefinition("TestCrdInvalidUpdate")
Expect(err).NotTo(HaveOccurred())
_, err = createCustomResource("test-cr-invalid-update", "default", "TestCrdInvalidUpdate")
Expect(err).NotTo(HaveOccurred())
defer func() {
_, err := makeRequest("DELETE", "/apis/example.com/v1/namespaces/default/testcrdinvalidupdates/test-cr-invalid-update", nil)
Expect(err).NotTo(HaveOccurred())
_, err = makeRequest("DELETE", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrdinvalidupdates.example.com", nil)
Expect(err).NotTo(HaveOccurred())
}()
patch := createMalformedPatch("test-cr-invalid-update", "default")
resp, err := makeRequest("PATCH", "/apis/example.com/v1/namespaces/default/testcrdinvalidupdates/test-cr-invalid-update", patch)
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusUnprocessableEntity), string(body))
})
It("修改同一命名空间其他同类资源", func() {
_, err := createCustomResourceDefinition("TestCrdOtherResource")
Expect(err).NotTo(HaveOccurred())
_, err = createCustomResource("test-cr-other-resource", "default", "TestCrdOtherResource")
Expect(err).NotTo(HaveOccurred())
_, err = createCustomResource("other-cr", "default", "TestCrdOtherResource")
Expect(err).NotTo(HaveOccurred())
defer func() {
_, err := makeRequest("DELETE", "/apis/example.com/v1/namespaces/default/testcrdotherresources/test-cr-other-resource", nil)
Expect(err).NotTo(HaveOccurred())
_, err = makeRequest("DELETE", "/apis/example.com/v1/namespaces/default/testcrdotherresources/other-cr", nil)
Expect(err).NotTo(HaveOccurred())
_, err = makeRequest("DELETE", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrdotherresources.example.com", nil)
Expect(err).NotTo(HaveOccurred())
}()
patch := createPatch("other-cr", "default")
resp, err := makeRequest("PATCH", "/apis/example.com/v1/namespaces/default/testcrdotherresources/test-cr-other-resource", patch)
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusBadRequest), string(body))
})
It("修改不存在的Namespace", func() {
_, err := createCustomResourceDefinition("TestCrdNonExistentNamespace")
Expect(err).NotTo(HaveOccurred())
_, err = createCustomResource("test-cr-nonexistent-namespace", "default", "TestCrdNonExistentNamespace")
Expect(err).NotTo(HaveOccurred())
defer func() {
_, err := makeRequest("DELETE", "/apis/example.com/v1/namespaces/default/testcrdnonexistentnamespaces/test-cr-nonexistent-namespace", nil)
Expect(err).NotTo(HaveOccurred())
_, err = makeRequest("DELETE", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrdnonexistentnamespaces.example.com", nil)
Expect(err).NotTo(HaveOccurred())
}()
patch := createPatch("test-cr-nonexistent-namespace", "nonexistent-namespace")
resp, err := makeRequest("PATCH", "/apis/example.com/v1/namespaces/default/testcrdnonexistentnamespaces/test-cr-nonexistent-namespace", patch)
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusBadRequest), string(body))
})
})
Context("CustomResource 删除", func() {
It("删除成功", func() {
_, err := createCustomResourceDefinition("TestCrdDelete")
Expect(err).NotTo(HaveOccurred())
_, err = createCustomResource("test-cr-delete", "default", "TestCrdDelete")
Expect(err).NotTo(HaveOccurred())
defer func() {
_, err = makeRequest("DELETE", "/apis/apiextensions.k8s.io/v1/customresourcedefinitions/testcrddeletes.example.com", nil)
Expect(err).NotTo(HaveOccurred())
}()
resp, err := makeRequest("DELETE", "/apis/example.com/v1/namespaces/default/testcrddeletes/test-cr-delete", nil)
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusOK), string(body))
})
})
})