mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-01-05 15:37:24 +00:00
remove todo: switch UpdatePodSpecForObject to work on v1.PodSpec, use info.VersionedObject, and avoid conversion completely
This commit is contained in:
@@ -18,24 +18,36 @@ package set
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
appsv1beta1 "k8s.io/api/apps/v1beta1"
|
||||
appsv1beta2 "k8s.io/api/apps/v1beta2"
|
||||
batchv1 "k8s.io/api/batch/v1"
|
||||
"k8s.io/api/core/v1"
|
||||
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/rest/fake"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
||||
"k8s.io/kubernetes/pkg/kubectl/resource"
|
||||
"k8s.io/kubernetes/pkg/kubectl/scheme"
|
||||
"k8s.io/kubernetes/pkg/printers"
|
||||
)
|
||||
|
||||
func TestResourcesLocal(t *testing.T) {
|
||||
f, tf, codec, ns := cmdtesting.NewAPIFactory()
|
||||
tf.Client = &fake.RESTClient{
|
||||
GroupVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion,
|
||||
GroupVersion: schema.GroupVersion{Version: ""},
|
||||
NegotiatedSerializer: ns,
|
||||
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
|
||||
t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req)
|
||||
@@ -43,7 +55,7 @@ func TestResourcesLocal(t *testing.T) {
|
||||
}),
|
||||
}
|
||||
tf.Namespace = "test"
|
||||
tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion}}
|
||||
tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}}
|
||||
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
cmd := NewCmdResources(f, buf, buf)
|
||||
@@ -79,7 +91,7 @@ func TestResourcesLocal(t *testing.T) {
|
||||
func TestSetMultiResourcesLimitsLocal(t *testing.T) {
|
||||
f, tf, codec, ns := cmdtesting.NewAPIFactory()
|
||||
tf.Client = &fake.RESTClient{
|
||||
GroupVersion: legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion,
|
||||
GroupVersion: schema.GroupVersion{Version: ""},
|
||||
NegotiatedSerializer: ns,
|
||||
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
|
||||
t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req)
|
||||
@@ -87,7 +99,7 @@ func TestSetMultiResourcesLimitsLocal(t *testing.T) {
|
||||
}),
|
||||
}
|
||||
tf.Namespace = "test"
|
||||
tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion}}
|
||||
tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}}
|
||||
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
cmd := NewCmdResources(f, buf, buf)
|
||||
@@ -120,3 +132,366 @@ func TestSetMultiResourcesLimitsLocal(t *testing.T) {
|
||||
t.Errorf("expected out:\n%s\nbut got:\n%s", expectedOut, buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetResourcesRemote(t *testing.T) {
|
||||
inputs := []struct {
|
||||
object runtime.Object
|
||||
apiPrefix, apiGroup, apiVersion string
|
||||
testAPIGroup string
|
||||
args []string
|
||||
}{
|
||||
{
|
||||
object: &extensionsv1beta1.ReplicaSet{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
|
||||
Spec: extensionsv1beta1.ReplicaSetSpec{
|
||||
Template: v1.PodTemplateSpec{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "nginx",
|
||||
Image: "nginx",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
testAPIGroup: "extensions",
|
||||
apiPrefix: "/apis", apiGroup: "extensions", apiVersion: "v1beta1",
|
||||
args: []string{"replicaset", "nginx"},
|
||||
},
|
||||
{
|
||||
object: &appsv1beta2.ReplicaSet{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
|
||||
Spec: appsv1beta2.ReplicaSetSpec{
|
||||
Template: v1.PodTemplateSpec{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "nginx",
|
||||
Image: "nginx",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
testAPIGroup: "extensions",
|
||||
apiPrefix: "/apis", apiGroup: "apps", apiVersion: "v1beta2",
|
||||
args: []string{"replicaset", "nginx"},
|
||||
},
|
||||
{
|
||||
object: &appsv1.ReplicaSet{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
|
||||
Spec: appsv1.ReplicaSetSpec{
|
||||
Template: v1.PodTemplateSpec{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "nginx",
|
||||
Image: "nginx",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
testAPIGroup: "extensions",
|
||||
apiPrefix: "/apis", apiGroup: "apps", apiVersion: "v1",
|
||||
args: []string{"replicaset", "nginx"},
|
||||
},
|
||||
{
|
||||
object: &extensionsv1beta1.DaemonSet{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
|
||||
Spec: extensionsv1beta1.DaemonSetSpec{
|
||||
Template: v1.PodTemplateSpec{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "nginx",
|
||||
Image: "nginx",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
testAPIGroup: "extensions",
|
||||
apiPrefix: "/apis", apiGroup: "extensions", apiVersion: "v1beta1",
|
||||
args: []string{"daemonset", "nginx"},
|
||||
},
|
||||
{
|
||||
object: &appsv1beta2.DaemonSet{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
|
||||
Spec: appsv1beta2.DaemonSetSpec{
|
||||
Template: v1.PodTemplateSpec{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "nginx",
|
||||
Image: "nginx",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
testAPIGroup: "extensions",
|
||||
apiPrefix: "/apis", apiGroup: "apps", apiVersion: "v1beta2",
|
||||
args: []string{"daemonset", "nginx"},
|
||||
},
|
||||
{
|
||||
object: &appsv1.DaemonSet{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
|
||||
Spec: appsv1.DaemonSetSpec{
|
||||
Template: v1.PodTemplateSpec{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "nginx",
|
||||
Image: "nginx",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
testAPIGroup: "extensions",
|
||||
apiPrefix: "/apis", apiGroup: "apps", apiVersion: "v1",
|
||||
args: []string{"daemonset", "nginx"},
|
||||
},
|
||||
{
|
||||
object: &extensionsv1beta1.Deployment{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
|
||||
Spec: extensionsv1beta1.DeploymentSpec{
|
||||
Template: v1.PodTemplateSpec{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "nginx",
|
||||
Image: "nginx",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
testAPIGroup: "extensions",
|
||||
apiPrefix: "/apis", apiGroup: "extensions", apiVersion: "v1beta1",
|
||||
args: []string{"deployment", "nginx"},
|
||||
},
|
||||
{
|
||||
object: &appsv1beta1.Deployment{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
|
||||
Spec: appsv1beta1.DeploymentSpec{
|
||||
Template: v1.PodTemplateSpec{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "nginx",
|
||||
Image: "nginx",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
testAPIGroup: "extensions",
|
||||
apiPrefix: "/apis", apiGroup: "apps", apiVersion: "v1beta1",
|
||||
args: []string{"deployment", "nginx"},
|
||||
},
|
||||
{
|
||||
object: &appsv1beta2.Deployment{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
|
||||
Spec: appsv1beta2.DeploymentSpec{
|
||||
Template: v1.PodTemplateSpec{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "nginx",
|
||||
Image: "nginx",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
testAPIGroup: "extensions",
|
||||
apiPrefix: "/apis", apiGroup: "apps", apiVersion: "v1beta2",
|
||||
args: []string{"deployment", "nginx"},
|
||||
},
|
||||
{
|
||||
object: &appsv1.Deployment{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
|
||||
Spec: appsv1.DeploymentSpec{
|
||||
Template: v1.PodTemplateSpec{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "nginx",
|
||||
Image: "nginx",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
testAPIGroup: "extensions",
|
||||
apiPrefix: "/apis", apiGroup: "apps", apiVersion: "v1",
|
||||
args: []string{"deployment", "nginx"},
|
||||
},
|
||||
{
|
||||
object: &appsv1beta1.StatefulSet{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
|
||||
Spec: appsv1beta1.StatefulSetSpec{
|
||||
Template: v1.PodTemplateSpec{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "nginx",
|
||||
Image: "nginx",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
testAPIGroup: "apps",
|
||||
apiPrefix: "/apis", apiGroup: "apps", apiVersion: "v1beta1",
|
||||
args: []string{"statefulset", "nginx"},
|
||||
},
|
||||
{
|
||||
object: &appsv1beta2.StatefulSet{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
|
||||
Spec: appsv1beta2.StatefulSetSpec{
|
||||
Template: v1.PodTemplateSpec{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "nginx",
|
||||
Image: "nginx",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
testAPIGroup: "apps",
|
||||
apiPrefix: "/apis", apiGroup: "apps", apiVersion: "v1beta2",
|
||||
args: []string{"statefulset", "nginx"},
|
||||
},
|
||||
{
|
||||
object: &appsv1.StatefulSet{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
|
||||
Spec: appsv1.StatefulSetSpec{
|
||||
Template: v1.PodTemplateSpec{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "nginx",
|
||||
Image: "nginx",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
testAPIGroup: "apps",
|
||||
apiPrefix: "/apis", apiGroup: "apps", apiVersion: "v1",
|
||||
args: []string{"statefulset", "nginx"},
|
||||
},
|
||||
{
|
||||
object: &batchv1.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
|
||||
Spec: batchv1.JobSpec{
|
||||
Template: v1.PodTemplateSpec{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "nginx",
|
||||
Image: "nginx",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
testAPIGroup: "batch",
|
||||
apiPrefix: "/apis", apiGroup: "batch", apiVersion: "v1",
|
||||
args: []string{"job", "nginx"},
|
||||
},
|
||||
{
|
||||
object: &v1.ReplicationController{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "nginx"},
|
||||
Spec: v1.ReplicationControllerSpec{
|
||||
Template: &v1.PodTemplateSpec{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "nginx",
|
||||
Image: "nginx",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
testAPIGroup: "",
|
||||
apiPrefix: "/api", apiGroup: "", apiVersion: "v1",
|
||||
args: []string{"replicationcontroller", "nginx"},
|
||||
},
|
||||
}
|
||||
for _, input := range inputs {
|
||||
groupVersion := schema.GroupVersion{Group: input.apiGroup, Version: input.apiVersion}
|
||||
testapi.Default = testapi.Groups[input.testAPIGroup]
|
||||
f, tf, _, ns := cmdtesting.NewAPIFactory()
|
||||
codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion)
|
||||
mapper, typer := f.Object()
|
||||
tf.Printer = &printers.NamePrinter{Decoders: []runtime.Decoder{testapi.Default.Codec()}, Typer: typer, Mapper: mapper}
|
||||
tf.Namespace = "test"
|
||||
tf.CategoryExpander = resource.LegacyCategoryExpander
|
||||
tf.Client = &fake.RESTClient{
|
||||
GroupVersion: groupVersion,
|
||||
NegotiatedSerializer: ns,
|
||||
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
|
||||
resourcePath := testapi.Default.ResourcePath(input.args[0]+"s", tf.Namespace, input.args[1])
|
||||
switch p, m := req.URL.Path, req.Method; {
|
||||
case p == resourcePath && m == http.MethodGet:
|
||||
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil
|
||||
case p == resourcePath && m == http.MethodPatch:
|
||||
stream, err := req.GetBody()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bytes, err := ioutil.ReadAll(stream)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
assert.Contains(t, string(bytes), "200m", fmt.Sprintf("resources not updated for %#v", input.object))
|
||||
return &http.Response{StatusCode: http.StatusOK, Header: defaultHeader(), Body: objBody(codec, input.object)}, nil
|
||||
default:
|
||||
t.Errorf("%s: unexpected request: %s %#v\n%#v", "resources", req.Method, req.URL, req)
|
||||
return nil, fmt.Errorf("unexpected request")
|
||||
}
|
||||
}),
|
||||
VersionedAPIPath: path.Join(input.apiPrefix, testapi.Default.GroupVersion().String()),
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
cmd := NewCmdResources(f, buf, buf)
|
||||
cmd.SetOutput(buf)
|
||||
cmd.Flags().Set("output", "yaml")
|
||||
opts := ResourcesOptions{
|
||||
Out: buf,
|
||||
Local: true,
|
||||
Limits: "cpu=200m,memory=512Mi",
|
||||
ContainerSelector: "*"}
|
||||
err := opts.Complete(f, cmd, input.args)
|
||||
if err == nil {
|
||||
err = opts.Validate()
|
||||
}
|
||||
if err == nil {
|
||||
err = opts.Run()
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user