1
16
17 package flowcontrol
18
19 import (
20 "encoding/json"
21 "testing"
22 "time"
23
24 flowcontrol "k8s.io/api/flowcontrol/v1"
25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26 machinerytypes "k8s.io/apimachinery/pkg/types"
27 "k8s.io/apimachinery/pkg/util/wait"
28 fcboot "k8s.io/apiserver/pkg/apis/flowcontrol/bootstrap"
29 flowcontrolapply "k8s.io/client-go/applyconfigurations/flowcontrol/v1"
30 clientset "k8s.io/client-go/kubernetes"
31 "k8s.io/klog/v2"
32 )
33
34 func TestConditionIsolation(t *testing.T) {
35 ctx, kubeConfig, closeFn := setup(t, 10, 10)
36 defer closeFn()
37
38 loopbackClient := clientset.NewForConfigOrDie(kubeConfig)
39
40 fsOrig := fcboot.SuggestedFlowSchemas[0]
41 t.Logf("Testing Status Condition isolation in FlowSchema %q", fsOrig.Name)
42 fsClient := loopbackClient.FlowcontrolV1().FlowSchemas()
43 var dangleOrig *flowcontrol.FlowSchemaCondition
44
45 wait.PollUntil(time.Second, func() (bool, error) {
46 fsGot, err := fsClient.Get(ctx, fsOrig.Name, metav1.GetOptions{})
47 if err != nil {
48 klog.Errorf("Failed to fetch FlowSchema %q: %v", fsOrig.Name, err)
49 return false, nil
50 }
51 dangleOrig = getCondition(fsGot.Status.Conditions, flowcontrol.FlowSchemaConditionDangling)
52 return dangleOrig != nil, nil
53 }, ctx.Done())
54
55 ssaType := flowcontrol.FlowSchemaConditionType("test-ssa")
56 patchSSA := flowcontrolapply.FlowSchema(fsOrig.Name).
57 WithStatus(flowcontrolapply.FlowSchemaStatus().
58 WithConditions(flowcontrolapply.FlowSchemaCondition().
59 WithType(ssaType).
60 WithStatus(flowcontrol.ConditionTrue).
61 WithReason("SSA test").
62 WithMessage("for testing").
63 WithLastTransitionTime(metav1.Now()),
64 ))
65
66 postSSA, err := fsClient.ApplyStatus(ctx, patchSSA, metav1.ApplyOptions{FieldManager: "ssa-test"})
67 if err != nil {
68 t.Error(err)
69 }
70 danglePostSSA := getCondition(postSSA.Status.Conditions, flowcontrol.FlowSchemaConditionDangling)
71 if danglePostSSA == nil || danglePostSSA.Status != dangleOrig.Status {
72 t.Errorf("Bad dangle condition after SSA, the FS is now %s", fmtFS(t, postSSA))
73 }
74 ssaPostSSA := getCondition(postSSA.Status.Conditions, ssaType)
75 if ssaPostSSA == nil || ssaPostSSA.Status != flowcontrol.ConditionTrue {
76 t.Errorf("Bad SSA condition after SSA, the FS is now %s", fmtFS(t, postSSA))
77 }
78
79 smpType := flowcontrol.FlowSchemaConditionType("test-smp")
80 smpBytes, err := makeFlowSchemaConditionPatch(flowcontrol.FlowSchemaCondition{
81 Type: smpType,
82 Status: flowcontrol.ConditionFalse,
83 Reason: "SMP test",
84 Message: "for testing too",
85 LastTransitionTime: metav1.Now(),
86 })
87 if err != nil {
88 t.Error(err)
89 }
90 postSMP, err := fsClient.Patch(ctx, fsOrig.Name, machinerytypes.StrategicMergePatchType, smpBytes,
91 metav1.PatchOptions{FieldManager: "smp-test"}, "status")
92 if err != nil {
93 t.Error(err)
94 }
95 if false {
96 danglePostSMP := getCondition(postSMP.Status.Conditions, flowcontrol.FlowSchemaConditionDangling)
97 if danglePostSMP == nil || danglePostSMP.Status != dangleOrig.Status {
98 t.Errorf("Bad dangle condition after SMP, the FS is now %s", fmtFS(t, postSMP))
99 }
100 ssaPostSMP := getCondition(postSMP.Status.Conditions, ssaType)
101 if ssaPostSMP == nil || ssaPostSMP.Status != flowcontrol.ConditionTrue {
102 t.Errorf("Bad SSA condition after SMP, the FS is now %s", fmtFS(t, postSMP))
103 }
104 }
105 smpPostSMP := getCondition(postSMP.Status.Conditions, smpType)
106 if smpPostSMP == nil || smpPostSMP.Status != flowcontrol.ConditionFalse {
107 t.Errorf("Bad SMP condition after SMP, the FS is now %s", fmtFS(t, postSMP))
108 }
109
110 }
111
112 func getCondition(conds []flowcontrol.FlowSchemaCondition, condType flowcontrol.FlowSchemaConditionType) *flowcontrol.FlowSchemaCondition {
113 for _, cond := range conds {
114 if cond.Type == condType {
115 return &cond
116 }
117 }
118 return nil
119 }
120
121
122 func makeFlowSchemaConditionPatch(condition flowcontrol.FlowSchemaCondition) ([]byte, error) {
123 o := struct {
124 Status flowcontrol.FlowSchemaStatus `json:"status"`
125 }{
126 Status: flowcontrol.FlowSchemaStatus{
127 Conditions: []flowcontrol.FlowSchemaCondition{
128 condition,
129 },
130 },
131 }
132 return json.Marshal(o)
133 }
134
135 func fmtFS(t *testing.T, fs *flowcontrol.FlowSchema) string {
136 asBytes, err := json.Marshal(fs)
137 if err != nil {
138 t.Error(err)
139 }
140 return string(asBytes)
141 }
142
View as plain text