...

Source file src/k8s.io/kubernetes/test/integration/apiserver/flowcontrol/fs_condition_test.go

Documentation: k8s.io/kubernetes/test/integration/apiserver/flowcontrol

     1  /*
     2  Copyright 2022 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    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 /* disabled until patch annotations go into the API (see https://github.com/kubernetes/kubernetes/issues/107574) */ {
    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  // makeFlowSchemaConditionPatch takes in a condition and returns the patch status as a json.
   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