mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 19:31:44 +00:00
Add Deployment resource lifecycle test as-is
This commit is contained in:
parent
a463b25c9d
commit
3149247932
@ -21,6 +21,7 @@ import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/onsi/ginkgo"
|
||||
@ -28,6 +29,10 @@ import (
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
unstructuredv1 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/dynamic"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
@ -67,6 +72,7 @@ var (
|
||||
var _ = SIGDescribe("Deployment", func() {
|
||||
var ns string
|
||||
var c clientset.Interface
|
||||
var dc dynamic.Interface
|
||||
|
||||
ginkgo.AfterEach(func() {
|
||||
failureTrap(c, ns)
|
||||
@ -77,6 +83,7 @@ var _ = SIGDescribe("Deployment", func() {
|
||||
ginkgo.BeforeEach(func() {
|
||||
c = f.ClientSet
|
||||
ns = f.Namespace.Name
|
||||
dc = f.DynamicClient
|
||||
})
|
||||
|
||||
ginkgo.It("deployment reaping should cascade to its replica sets and pods", func() {
|
||||
@ -134,6 +141,270 @@ var _ = SIGDescribe("Deployment", func() {
|
||||
})
|
||||
// TODO: add tests that cover deployment.Spec.MinReadySeconds once we solved clock-skew issues
|
||||
// See https://github.com/kubernetes/kubernetes/issues/29229
|
||||
|
||||
ginkgo.It("should run the lifecycle of a Deployment", func() {
|
||||
deploymentResource := schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}
|
||||
testDeploymentName := "test-deployment"
|
||||
testDeploymentInitialImage := "nginx"
|
||||
testDeploymentPatchImage := "alpine"
|
||||
testDeploymentUpdateImage := "httpd"
|
||||
testDeploymentDefaultReplicas := int32(3)
|
||||
testDeploymentMinimumReplicas := int32(1)
|
||||
testDeploymentNoReplicas := int32(0)
|
||||
// TODO labels
|
||||
// TODO flat labels
|
||||
testDeploymentLabelSelectors := metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{"app": "test-deployment"},
|
||||
}
|
||||
testNamespaceName := "default"
|
||||
|
||||
fmt.Println("creating a Deployment")
|
||||
testDeployment := appsv1.Deployment{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: testDeploymentName,
|
||||
Labels: map[string]string{"test-deployment-static": "true"},
|
||||
},
|
||||
Spec: appsv1.DeploymentSpec{
|
||||
Replicas: &testDeploymentDefaultReplicas,
|
||||
Selector: &testDeploymentLabelSelectors,
|
||||
Template: v1.PodTemplateSpec{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: testDeploymentLabelSelectors.MatchLabels,
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{{
|
||||
Name: testDeploymentName,
|
||||
Image: testDeploymentInitialImage,
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
_, err := f.ClientSet.AppsV1().Deployments(testNamespaceName).Create(context.TODO(), &testDeployment, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("watching for the Deployment to be added")
|
||||
dplmtWatchTimeoutSeconds := int64(180)
|
||||
dplmtWatch, err := f.ClientSet.AppsV1().Deployments(testNamespaceName).Watch(context.TODO(), metav1.ListOptions{LabelSelector: "test-deployment-static=true", TimeoutSeconds: &dplmtWatchTimeoutSeconds})
|
||||
if err != nil {
|
||||
fmt.Println(err, "Failed to setup watch on newly created Deployment")
|
||||
return
|
||||
}
|
||||
|
||||
dplmtWatchChan := dplmtWatch.ResultChan()
|
||||
for event := range dplmtWatchChan {
|
||||
if event.Type == watch.Added {
|
||||
break
|
||||
}
|
||||
}
|
||||
defer func() {
|
||||
fmt.Println("deleting the Deployment")
|
||||
err = f.ClientSet.AppsV1().Deployments(testNamespaceName).DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: "test-deployment-static=true"})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
for event := range dplmtWatchChan {
|
||||
deployment, ok := event.Object.(*appsv1.Deployment)
|
||||
if ok != true {
|
||||
fmt.Println("unable to convert event.Object type")
|
||||
return
|
||||
}
|
||||
if event.Type == watch.Deleted && deployment.ObjectMeta.Name == testDeploymentName {
|
||||
break
|
||||
}
|
||||
}
|
||||
}()
|
||||
fmt.Println("waiting for all Replicas to be Ready")
|
||||
for event := range dplmtWatchChan {
|
||||
deployment, ok := event.Object.(*appsv1.Deployment)
|
||||
if ok != true {
|
||||
fmt.Println("unable to convert event.Object type")
|
||||
return
|
||||
}
|
||||
if deployment.Status.AvailableReplicas == testDeploymentDefaultReplicas &&
|
||||
deployment.Status.ReadyReplicas == testDeploymentDefaultReplicas {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("patching the Deployment")
|
||||
deploymentPatch, err := json.Marshal(map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]string{"test-deployment": "patched"},
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"replicas": testDeploymentMinimumReplicas,
|
||||
"template": map[string]interface{}{
|
||||
"spec": map[string]interface{}{
|
||||
"containers": []map[string]interface{}{{
|
||||
"name": testDeploymentName,
|
||||
"image": testDeploymentPatchImage,
|
||||
"command": []string{"/bin/sleep", "100000"},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println(err, "failed to Marshal Deployment JSON patch")
|
||||
return
|
||||
}
|
||||
_, err = f.ClientSet.AppsV1().Deployments(testNamespaceName).Patch(context.TODO(), testDeploymentName, types.StrategicMergePatchType, []byte(deploymentPatch), metav1.PatchOptions{})
|
||||
if err != nil {
|
||||
fmt.Println(err, "failed to patch Deployment")
|
||||
return
|
||||
}
|
||||
|
||||
for event := range dplmtWatchChan {
|
||||
if event.Type == watch.Modified {
|
||||
break
|
||||
}
|
||||
}
|
||||
fmt.Println("waiting for Replicas to scale")
|
||||
for event := range dplmtWatchChan {
|
||||
deployment, ok := event.Object.(*appsv1.Deployment)
|
||||
if ok != true {
|
||||
fmt.Println("unable to convert event.Object type")
|
||||
return
|
||||
}
|
||||
if deployment.Status.AvailableReplicas == testDeploymentMinimumReplicas &&
|
||||
deployment.Status.ReadyReplicas == testDeploymentMinimumReplicas {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("listing Deployments")
|
||||
deploymentsList, err := f.ClientSet.AppsV1().Deployments("").List(context.TODO(), metav1.ListOptions{LabelSelector: "test-deployment-static=true"})
|
||||
if err != nil {
|
||||
fmt.Println(err, "failed to list Deployments")
|
||||
return
|
||||
}
|
||||
foundDeployment := false
|
||||
for _, deploymentItem := range deploymentsList.Items {
|
||||
if deploymentItem.ObjectMeta.Name == testDeploymentName &&
|
||||
deploymentItem.ObjectMeta.Namespace == testNamespaceName &&
|
||||
deploymentItem.ObjectMeta.Labels["test-deployment-static"] == "true" &&
|
||||
*deploymentItem.Spec.Replicas == testDeploymentMinimumReplicas &&
|
||||
deploymentItem.Spec.Template.Spec.Containers[0].Image == testDeploymentPatchImage {
|
||||
foundDeployment = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if foundDeployment != true {
|
||||
fmt.Println("unable to find the Deployment in list")
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("updating the DeploymentStatus")
|
||||
testDeploymentUpdate := testDeployment
|
||||
testDeploymentUpdate.ObjectMeta.Labels["test-deployment"] = "updated"
|
||||
testDeploymentUpdate.Spec.Template.Spec.Containers[0].Image = testDeploymentUpdateImage
|
||||
testDeploymentDefaultReplicasPointer := &testDeploymentDefaultReplicas
|
||||
testDeploymentUpdate.Spec.Replicas = testDeploymentDefaultReplicasPointer
|
||||
testDeploymentUpdate.Status.ReadyReplicas = testDeploymentNoReplicas
|
||||
testDeploymentUpdateUnstructuredMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&testDeploymentUpdate)
|
||||
if err != nil {
|
||||
fmt.Println(err, "failed to convert to unstructured")
|
||||
}
|
||||
testDeploymentUpdateUnstructured := unstructuredv1.Unstructured{
|
||||
Object: testDeploymentUpdateUnstructuredMap,
|
||||
}
|
||||
// currently this hasn't been able to hit the endpoint replaceAppsV1NamespacedDeploymentStatus
|
||||
_, err = dc.Resource(deploymentResource).Namespace(testNamespaceName).Update(context.TODO(), &testDeploymentUpdateUnstructured, metav1.UpdateOptions{}) //, "status")
|
||||
if err != nil {
|
||||
fmt.Println(err, "failed to update the DeploymentStatus")
|
||||
return
|
||||
}
|
||||
for event := range dplmtWatchChan {
|
||||
if event.Type == watch.Modified {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("fetching the DeploymentStatus")
|
||||
deploymentGetUnstructured, err := dc.Resource(deploymentResource).Namespace(testNamespaceName).Get(context.TODO(), testDeploymentName, metav1.GetOptions{}, "status")
|
||||
if err != nil {
|
||||
fmt.Println(err, "failed to fetch the Deployment")
|
||||
return
|
||||
}
|
||||
deploymentGet := appsv1.Deployment{}
|
||||
err = runtime.DefaultUnstructuredConverter.FromUnstructured(deploymentGetUnstructured.Object, &deploymentGet)
|
||||
if err != nil {
|
||||
fmt.Println(err, "failed to convert the unstructured response to a Deployment")
|
||||
return
|
||||
}
|
||||
if !(deploymentGet.Spec.Template.Spec.Containers[0].Image == testDeploymentUpdateImage || deploymentGet.Status.ReadyReplicas == testDeploymentNoReplicas || deploymentGet.ObjectMeta.Labels["test-deployment"] == "updated") {
|
||||
fmt.Println("failed to update the Deployment (did not return correct values)")
|
||||
return
|
||||
}
|
||||
for event := range dplmtWatchChan {
|
||||
if event.Type == watch.Modified {
|
||||
break
|
||||
}
|
||||
}
|
||||
for event := range dplmtWatchChan {
|
||||
deployment, ok := event.Object.(*appsv1.Deployment)
|
||||
if ok != true {
|
||||
fmt.Println("failed to convert event Object to a Deployment")
|
||||
return
|
||||
}
|
||||
if deployment.Status.ReadyReplicas == testDeploymentDefaultReplicas {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("patching the DeploymentStatus")
|
||||
deploymentStatusPatch, err := json.Marshal(map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]string{"test-deployment": "patched-status"},
|
||||
},
|
||||
"status": map[string]interface{}{
|
||||
"readyReplicas": testDeploymentNoReplicas,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println(err, "failed to Marshal Deployment JSON patch")
|
||||
return
|
||||
}
|
||||
dc.Resource(deploymentResource).Namespace(testNamespaceName).Patch(context.TODO(), testDeploymentName, types.StrategicMergePatchType, []byte(deploymentStatusPatch), metav1.PatchOptions{}, "status")
|
||||
|
||||
fmt.Println("fetching the DeploymentStatus")
|
||||
deploymentGetUnstructured, err = dc.Resource(deploymentResource).Namespace(testNamespaceName).Get(context.TODO(), testDeploymentName, metav1.GetOptions{}, "status")
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err, "failed to fetch the DeploymentStatus")
|
||||
return
|
||||
}
|
||||
deploymentGet = appsv1.Deployment{}
|
||||
err = runtime.DefaultUnstructuredConverter.FromUnstructured(deploymentGetUnstructured.Object, &deploymentGet)
|
||||
if err != nil {
|
||||
fmt.Println(err, "failed to convert the unstructured response to a Deployment")
|
||||
return
|
||||
}
|
||||
if !(deploymentGet.Spec.Template.Spec.Containers[0].Image == testDeploymentUpdateImage || deploymentGet.Status.ReadyReplicas == 0 || deploymentGet.ObjectMeta.Labels["test-deployment"] == "patched-status") {
|
||||
fmt.Println("failed to update the Deployment (did not return correct values)")
|
||||
return
|
||||
}
|
||||
for event := range dplmtWatchChan {
|
||||
if event.Type == watch.Modified {
|
||||
break
|
||||
}
|
||||
}
|
||||
for event := range dplmtWatchChan {
|
||||
deployment, ok := event.Object.(*appsv1.Deployment)
|
||||
if ok != true {
|
||||
fmt.Println("failed to convert event Object to a Deployment")
|
||||
return
|
||||
}
|
||||
if deployment.Status.ReadyReplicas == testDeploymentDefaultReplicas {
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
func failureTrap(c clientset.Interface, ns string) {
|
||||
@ -372,7 +643,6 @@ func testDeploymentCleanUpPolicy(f *framework.Framework) {
|
||||
w, err := c.CoreV1().Pods(ns).Watch(context.TODO(), options)
|
||||
framework.ExpectNoError(err)
|
||||
go func() {
|
||||
defer ginkgo.GinkgoRecover()
|
||||
// There should be only one pod being created, which is the pod with the agnhost image.
|
||||
// The old RS shouldn't create new pod when deployment controller adding pod template hash label to its selector.
|
||||
numPodCreation := 1
|
||||
|
Loading…
Reference in New Issue
Block a user