Skip to content

Commit 509bbed

Browse files
committed
Add a test ensuring all /scale sub-resources return table
Signed-off-by: Maciej Szulik <[email protected]>
1 parent 1fa9952 commit 509bbed

File tree

1 file changed

+198
-0
lines changed

1 file changed

+198
-0
lines changed

test/integration/apiserver/apiserver_test.go

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ import (
8080
"k8s.io/kubernetes/test/integration/etcd"
8181
"k8s.io/kubernetes/test/integration/framework"
8282
"k8s.io/kubernetes/test/utils/ktesting"
83+
"k8s.io/utils/ptr"
8384
)
8485

8586
func setup(t *testing.T, groupVersions ...schema.GroupVersion) (context.Context, clientset.Interface, *restclient.Config, framework.TearDownFunc) {
@@ -1677,6 +1678,203 @@ func TestGetSubresourcesAsTables(t *testing.T) {
16771678
}
16781679
}
16791680

1681+
func TestGetScaleSubresourceAsTableForAllBuiltins(t *testing.T) {
1682+
// KUBE_APISERVER_SERVE_REMOVED_APIS_FOR_ONE_RELEASE allows for APIs pending removal to not block tests
1683+
t.Setenv("KUBE_APISERVER_SERVE_REMOVED_APIS_FOR_ONE_RELEASE", "true")
1684+
1685+
// Enable all features for testing
1686+
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, "AllAlpha", true)
1687+
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, "AllBeta", true)
1688+
1689+
testNamespace := "test-scale"
1690+
server := kubeapiservertesting.StartTestServerOrDie(t, nil, framework.DefaultTestServerFlags(), framework.SharedEtcd())
1691+
defer server.TearDownFn()
1692+
1693+
clientset := clientset.NewForConfigOrDie(server.ClientConfig)
1694+
1695+
ns := framework.CreateNamespaceOrDie(clientset, testNamespace, t)
1696+
defer framework.DeleteNamespaceOrDie(clientset, ns, t)
1697+
1698+
scaleResources := map[string]runtime.Object{
1699+
"deployments.apps/v1": &apps.Deployment{
1700+
ObjectMeta: metav1.ObjectMeta{
1701+
Name: "dummy",
1702+
},
1703+
Spec: apps.DeploymentSpec{
1704+
Replicas: ptr.To[int32](1),
1705+
Selector: &metav1.LabelSelector{
1706+
MatchLabels: map[string]string{
1707+
"app": "dummy",
1708+
},
1709+
},
1710+
Template: v1.PodTemplateSpec{
1711+
ObjectMeta: metav1.ObjectMeta{
1712+
Labels: map[string]string{
1713+
"app": "dummy",
1714+
},
1715+
},
1716+
Spec: v1.PodSpec{
1717+
Containers: []v1.Container{
1718+
{
1719+
Name: "dummy-container",
1720+
Image: "nginx:latest",
1721+
},
1722+
},
1723+
},
1724+
},
1725+
},
1726+
},
1727+
"replicasets.apps/v1": &apps.ReplicaSet{
1728+
ObjectMeta: metav1.ObjectMeta{
1729+
Name: "dummy",
1730+
},
1731+
Spec: apps.ReplicaSetSpec{
1732+
Replicas: ptr.To[int32](1),
1733+
Selector: &metav1.LabelSelector{
1734+
MatchLabels: map[string]string{
1735+
"app": "dummy",
1736+
},
1737+
},
1738+
Template: v1.PodTemplateSpec{
1739+
ObjectMeta: metav1.ObjectMeta{
1740+
Labels: map[string]string{
1741+
"app": "dummy",
1742+
},
1743+
},
1744+
Spec: v1.PodSpec{
1745+
Containers: []v1.Container{
1746+
{
1747+
Name: "dummy-container",
1748+
Image: "nginx:latest",
1749+
},
1750+
},
1751+
},
1752+
},
1753+
},
1754+
},
1755+
"statefulsets.apps/v1": &apps.StatefulSet{
1756+
ObjectMeta: metav1.ObjectMeta{
1757+
Name: "dummy",
1758+
},
1759+
Spec: apps.StatefulSetSpec{
1760+
ServiceName: "dummy",
1761+
Replicas: ptr.To[int32](1),
1762+
Selector: &metav1.LabelSelector{
1763+
MatchLabels: map[string]string{
1764+
"app": "dummy",
1765+
},
1766+
},
1767+
Template: v1.PodTemplateSpec{
1768+
ObjectMeta: metav1.ObjectMeta{
1769+
Labels: map[string]string{
1770+
"app": "dummy",
1771+
},
1772+
},
1773+
Spec: v1.PodSpec{
1774+
Containers: []v1.Container{
1775+
{
1776+
Name: "dummy-container",
1777+
Image: "nginx:latest",
1778+
},
1779+
},
1780+
},
1781+
},
1782+
},
1783+
},
1784+
"replicationcontrollers.v1": &v1.ReplicationController{
1785+
ObjectMeta: metav1.ObjectMeta{
1786+
Name: "dummy",
1787+
},
1788+
Spec: v1.ReplicationControllerSpec{
1789+
Replicas: ptr.To[int32](1),
1790+
Selector: map[string]string{
1791+
"app": "dummy",
1792+
},
1793+
Template: &v1.PodTemplateSpec{
1794+
ObjectMeta: metav1.ObjectMeta{
1795+
Labels: map[string]string{
1796+
"app": "dummy",
1797+
},
1798+
},
1799+
Spec: v1.PodSpec{
1800+
Containers: []v1.Container{
1801+
{
1802+
Name: "dummy-container",
1803+
Image: "nginx:latest",
1804+
},
1805+
},
1806+
},
1807+
},
1808+
},
1809+
},
1810+
}
1811+
1812+
_, serverResources, err := clientset.Discovery().ServerGroupsAndResources()
1813+
if err != nil {
1814+
t.Fatal(err)
1815+
}
1816+
1817+
for _, resourceList := range serverResources {
1818+
for _, resource := range resourceList.APIResources {
1819+
if !strings.Contains(resource.Name, "/scale") {
1820+
continue
1821+
}
1822+
resourceName := strings.Split(resource.Name, "/")[0]
1823+
// we can safely skip error here, since the group version is coming from the server
1824+
groupVersion, _ := schema.ParseGroupVersion(resourceList.GroupVersion)
1825+
1826+
t.Run(resourceName, func(t *testing.T) {
1827+
_, ctx := ktesting.NewTestContext(t)
1828+
scaleResourceObjName := fmt.Sprintf("%s.%s", resourceName, resourceList.GroupVersion)
1829+
obj, ok := scaleResources[scaleResourceObjName]
1830+
if !ok {
1831+
t.Fatalf("sample resource for %s not found in scaleResources", scaleResourceObjName)
1832+
}
1833+
1834+
cfg := dynamic.ConfigFor(server.ClientConfig)
1835+
if len(groupVersion.Group) == 0 {
1836+
cfg = dynamic.ConfigFor(server.ClientConfig)
1837+
cfg.APIPath = "/api"
1838+
} else {
1839+
cfg.APIPath = "/apis"
1840+
}
1841+
cfg.GroupVersion = &groupVersion
1842+
client, err := restclient.RESTClientFor(cfg)
1843+
if err != nil {
1844+
t.Fatalf("failed to create RESTClient: %v", err)
1845+
}
1846+
1847+
err = client.Post().
1848+
NamespaceIfScoped(testNamespace, resource.Namespaced).Resource(resourceName).
1849+
VersionedParams(&metav1.CreateOptions{}, metav1.ParameterCodec).
1850+
Body(obj).Do(ctx).Error()
1851+
if err != nil {
1852+
t.Fatalf("failed to create object: %v", err)
1853+
}
1854+
1855+
metaAccessor, err := meta.Accessor(obj)
1856+
if err != nil {
1857+
t.Fatalf("failed to get metadata accessor: %v", err)
1858+
}
1859+
res := client.Get().
1860+
NamespaceIfScoped(testNamespace, resource.Namespaced).Resource(resourceName).
1861+
SetHeader("Accept", "application/json;as=Table;g=meta.k8s.io;v=v1").
1862+
Name(metaAccessor.GetName()).
1863+
SubResource("scale").
1864+
Do(ctx)
1865+
resObj, err := res.Get()
1866+
if err != nil {
1867+
t.Fatalf("failed to retrieve object from response: %v", err)
1868+
}
1869+
actualKind := resObj.GetObjectKind().GroupVersionKind().Kind
1870+
if actualKind != "Table" {
1871+
t.Fatalf("Expected Kind 'Table', got '%v'", actualKind)
1872+
}
1873+
})
1874+
}
1875+
}
1876+
}
1877+
16801878
func TestTransform(t *testing.T) {
16811879
testNamespace := "test-transform"
16821880
tearDown, config, _, err := fixtures.StartDefaultServer(t)

0 commit comments

Comments
 (0)