sigs.k8s.io/cluster-api@v1.7.1/exp/topology/scope/hookresponsetracker_test.go (about)

     1  /*
     2  Copyright 2021 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 scope
    18  
    19  import (
    20  	"testing"
    21  	"time"
    22  
    23  	. "github.com/onsi/gomega"
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  
    26  	runtimecatalog "sigs.k8s.io/cluster-api/exp/runtime/catalog"
    27  	runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
    28  )
    29  
    30  func TestHookResponseTracker_AggregateRetryAfter(t *testing.T) {
    31  	nonBlockingBeforeClusterCreateResponse := &runtimehooksv1.BeforeClusterCreateResponse{
    32  		CommonRetryResponse: runtimehooksv1.CommonRetryResponse{
    33  			RetryAfterSeconds: int32(0),
    34  			CommonResponse: runtimehooksv1.CommonResponse{
    35  				Status: runtimehooksv1.ResponseStatusSuccess,
    36  			},
    37  		},
    38  	}
    39  	blockingBeforeClusterCreateResponse := &runtimehooksv1.BeforeClusterCreateResponse{
    40  		CommonRetryResponse: runtimehooksv1.CommonRetryResponse{
    41  			RetryAfterSeconds: int32(10),
    42  			CommonResponse: runtimehooksv1.CommonResponse{
    43  				Status: runtimehooksv1.ResponseStatusSuccess,
    44  			},
    45  		},
    46  	}
    47  
    48  	nonBlockingBeforeClusterUpgradeResponse := &runtimehooksv1.BeforeClusterUpgradeResponse{
    49  		CommonRetryResponse: runtimehooksv1.CommonRetryResponse{
    50  			RetryAfterSeconds: int32(0),
    51  			CommonResponse: runtimehooksv1.CommonResponse{
    52  				Status: runtimehooksv1.ResponseStatusSuccess,
    53  			},
    54  		},
    55  	}
    56  	blockingBeforeClusterUpgradeResponse := &runtimehooksv1.BeforeClusterUpgradeResponse{
    57  		CommonRetryResponse: runtimehooksv1.CommonRetryResponse{
    58  			RetryAfterSeconds: int32(5),
    59  			CommonResponse: runtimehooksv1.CommonResponse{
    60  				Status: runtimehooksv1.ResponseStatusSuccess,
    61  			},
    62  		},
    63  	}
    64  
    65  	t.Run("AggregateRetryAfter should return non zero value if there are any blocking hook responses", func(t *testing.T) {
    66  		g := NewWithT(t)
    67  
    68  		hrt := NewHookResponseTracker()
    69  		hrt.Add(runtimehooksv1.BeforeClusterCreate, blockingBeforeClusterCreateResponse)
    70  		hrt.Add(runtimehooksv1.BeforeClusterUpgrade, nonBlockingBeforeClusterUpgradeResponse)
    71  
    72  		g.Expect(hrt.AggregateRetryAfter()).To(Equal(time.Duration(10) * time.Second))
    73  	})
    74  	t.Run("AggregateRetryAfter should return zero value if there are no blocking hook responses", func(t *testing.T) {
    75  		g := NewWithT(t)
    76  
    77  		hrt := NewHookResponseTracker()
    78  		hrt.Add(runtimehooksv1.BeforeClusterCreate, nonBlockingBeforeClusterCreateResponse)
    79  		hrt.Add(runtimehooksv1.BeforeClusterUpgrade, nonBlockingBeforeClusterUpgradeResponse)
    80  
    81  		g.Expect(hrt.AggregateRetryAfter()).To(Equal(time.Duration(0)))
    82  	})
    83  	t.Run("AggregateRetryAfter should return the lowest non-zero value if there are multiple blocking hook responses", func(t *testing.T) {
    84  		g := NewWithT(t)
    85  
    86  		hrt := NewHookResponseTracker()
    87  		hrt.Add(runtimehooksv1.BeforeClusterCreate, blockingBeforeClusterCreateResponse)
    88  		hrt.Add(runtimehooksv1.BeforeClusterUpgrade, blockingBeforeClusterUpgradeResponse)
    89  
    90  		g.Expect(hrt.AggregateRetryAfter()).To(Equal(time.Duration(5) * time.Second))
    91  	})
    92  }
    93  
    94  func TestHookResponseTracker_AggregateMessage(t *testing.T) {
    95  	nonBlockingBeforeClusterCreateResponse := &runtimehooksv1.BeforeClusterCreateResponse{
    96  		CommonRetryResponse: runtimehooksv1.CommonRetryResponse{
    97  			RetryAfterSeconds: int32(0),
    98  			CommonResponse: runtimehooksv1.CommonResponse{
    99  				Status: runtimehooksv1.ResponseStatusSuccess,
   100  			},
   101  		},
   102  	}
   103  	blockingBeforeClusterCreateResponse := &runtimehooksv1.BeforeClusterCreateResponse{
   104  		CommonRetryResponse: runtimehooksv1.CommonRetryResponse{
   105  			RetryAfterSeconds: int32(10),
   106  			CommonResponse: runtimehooksv1.CommonResponse{
   107  				Status: runtimehooksv1.ResponseStatusSuccess,
   108  			},
   109  		},
   110  	}
   111  
   112  	nonBlockingBeforeClusterUpgradeResponse := &runtimehooksv1.BeforeClusterUpgradeResponse{
   113  		CommonRetryResponse: runtimehooksv1.CommonRetryResponse{
   114  			RetryAfterSeconds: int32(0),
   115  			CommonResponse: runtimehooksv1.CommonResponse{
   116  				Status: runtimehooksv1.ResponseStatusSuccess,
   117  			},
   118  		},
   119  	}
   120  	blockingBeforeClusterUpgradeResponse := &runtimehooksv1.BeforeClusterUpgradeResponse{
   121  		CommonRetryResponse: runtimehooksv1.CommonRetryResponse{
   122  			RetryAfterSeconds: int32(5),
   123  			CommonResponse: runtimehooksv1.CommonResponse{
   124  				Status: runtimehooksv1.ResponseStatusSuccess,
   125  			},
   126  		},
   127  	}
   128  
   129  	t.Run("AggregateMessage should return a message with the names of all the blocking hooks", func(t *testing.T) {
   130  		g := NewWithT(t)
   131  
   132  		hrt := NewHookResponseTracker()
   133  		hrt.Add(runtimehooksv1.BeforeClusterCreate, blockingBeforeClusterCreateResponse)
   134  		hrt.Add(runtimehooksv1.BeforeClusterUpgrade, blockingBeforeClusterUpgradeResponse)
   135  
   136  		g.Expect(hrt.AggregateMessage()).To(ContainSubstring(runtimecatalog.HookName(runtimehooksv1.BeforeClusterCreate)))
   137  		g.Expect(hrt.AggregateMessage()).To(ContainSubstring(runtimecatalog.HookName(runtimehooksv1.BeforeClusterUpgrade)))
   138  	})
   139  	t.Run("AggregateMessage should return empty string if there are no blocking hook responses", func(t *testing.T) {
   140  		g := NewWithT(t)
   141  
   142  		hrt := NewHookResponseTracker()
   143  		hrt.Add(runtimehooksv1.BeforeClusterCreate, nonBlockingBeforeClusterCreateResponse)
   144  		hrt.Add(runtimehooksv1.BeforeClusterUpgrade, nonBlockingBeforeClusterUpgradeResponse)
   145  
   146  		g.Expect(hrt.AggregateMessage()).To(Equal(""))
   147  	})
   148  }
   149  
   150  func TestHookResponseTracker_IsBlocking(t *testing.T) {
   151  	nonBlockingBeforeClusterCreateResponse := &runtimehooksv1.BeforeClusterCreateResponse{
   152  		CommonRetryResponse: runtimehooksv1.CommonRetryResponse{
   153  			RetryAfterSeconds: int32(0),
   154  			CommonResponse: runtimehooksv1.CommonResponse{
   155  				Status: runtimehooksv1.ResponseStatusSuccess,
   156  			},
   157  		},
   158  	}
   159  	blockingBeforeClusterCreateResponse := &runtimehooksv1.BeforeClusterCreateResponse{
   160  		CommonRetryResponse: runtimehooksv1.CommonRetryResponse{
   161  			RetryAfterSeconds: int32(10),
   162  			CommonResponse: runtimehooksv1.CommonResponse{
   163  				Status: runtimehooksv1.ResponseStatusSuccess,
   164  			},
   165  		},
   166  	}
   167  
   168  	afterClusterUpgradeResponse := &runtimehooksv1.AfterClusterUpgradeResponse{
   169  		TypeMeta:       metav1.TypeMeta{},
   170  		CommonResponse: runtimehooksv1.CommonResponse{},
   171  	}
   172  
   173  	t.Run("should return true if the tracker received a blocking response for the hook", func(t *testing.T) {
   174  		g := NewWithT(t)
   175  
   176  		hrt := NewHookResponseTracker()
   177  		hrt.Add(runtimehooksv1.BeforeClusterCreate, blockingBeforeClusterCreateResponse)
   178  
   179  		g.Expect(hrt.IsBlocking(runtimehooksv1.BeforeClusterCreate)).To(BeTrue())
   180  	})
   181  
   182  	t.Run("should return false if the tracker received a non blocking response for the hook", func(t *testing.T) {
   183  		g := NewWithT(t)
   184  
   185  		hrt := NewHookResponseTracker()
   186  		hrt.Add(runtimehooksv1.BeforeClusterCreate, nonBlockingBeforeClusterCreateResponse)
   187  
   188  		g.Expect(hrt.IsBlocking(runtimehooksv1.BeforeClusterCreate)).To(BeFalse())
   189  	})
   190  
   191  	t.Run("should return false if the tracker did not receive a response for the hook", func(t *testing.T) {
   192  		g := NewWithT(t)
   193  		hrt := NewHookResponseTracker()
   194  		g.Expect(hrt.IsBlocking(runtimehooksv1.BeforeClusterCreate)).To(BeFalse())
   195  	})
   196  
   197  	t.Run("should return false if the hook is non-blocking", func(t *testing.T) {
   198  		g := NewWithT(t)
   199  		hrt := NewHookResponseTracker()
   200  		// AfterClusterUpgradeHook is non-blocking.
   201  		hrt.Add(runtimehooksv1.AfterClusterUpgrade, afterClusterUpgradeResponse)
   202  		g.Expect(hrt.IsBlocking(runtimehooksv1.AfterClusterUpgrade)).To(BeFalse())
   203  	})
   204  }