k8s.io/apiserver@v0.31.1/pkg/endpoints/discovery/aggregated/fake.go (about)

     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 aggregated
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"net/http"
    23  	"reflect"
    24  	"sync"
    25  	"time"
    26  
    27  	"github.com/emicklei/go-restful/v3"
    28  	"github.com/google/go-cmp/cmp"
    29  	apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
    30  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    31  	"k8s.io/apimachinery/pkg/util/wait"
    32  )
    33  
    34  type FakeResourceManager interface {
    35  	ResourceManager
    36  	Expect() ResourceManager
    37  
    38  	HasExpectedNumberActions() bool
    39  	Validate() error
    40  	WaitForActions(ctx context.Context, timeout time.Duration) error
    41  }
    42  
    43  func NewFakeResourceManager() FakeResourceManager {
    44  	return &fakeResourceManager{}
    45  }
    46  
    47  // a resource manager with helper functions for checking the actions
    48  // match expected. For Use in tests
    49  type fakeResourceManager struct {
    50  	recorderResourceManager
    51  	expect recorderResourceManager
    52  }
    53  
    54  // a resource manager which instead of managing a discovery document,
    55  // simply records the calls to its interface functoins for testing
    56  type recorderResourceManager struct {
    57  	lock    sync.RWMutex
    58  	Actions []recorderResourceManagerAction
    59  }
    60  
    61  var _ ResourceManager = &fakeResourceManager{}
    62  var _ ResourceManager = &recorderResourceManager{}
    63  
    64  // Storage type for a call to the resource manager
    65  type recorderResourceManagerAction struct {
    66  	Type    string
    67  	Group   string
    68  	Version string
    69  	Value   interface{}
    70  }
    71  
    72  func (f *fakeResourceManager) Expect() ResourceManager {
    73  	return &f.expect
    74  }
    75  
    76  func (f *fakeResourceManager) HasExpectedNumberActions() bool {
    77  	f.lock.RLock()
    78  	defer f.lock.RUnlock()
    79  
    80  	f.expect.lock.RLock()
    81  	defer f.expect.lock.RUnlock()
    82  
    83  	return len(f.Actions) >= len(f.expect.Actions)
    84  }
    85  
    86  func (f *fakeResourceManager) Validate() error {
    87  	f.lock.RLock()
    88  	defer f.lock.RUnlock()
    89  
    90  	f.expect.lock.RLock()
    91  	defer f.expect.lock.RUnlock()
    92  
    93  	if !reflect.DeepEqual(f.expect.Actions, f.Actions) {
    94  		return errors.New(cmp.Diff(f.expect.Actions, f.Actions))
    95  	}
    96  	return nil
    97  }
    98  
    99  func (f *fakeResourceManager) WaitForActions(ctx context.Context, timeout time.Duration) error {
   100  	err := wait.PollImmediateWithContext(
   101  		ctx,
   102  		100*time.Millisecond, // try every 100ms
   103  		timeout,              // timeout after timeout
   104  		func(ctx context.Context) (done bool, err error) {
   105  			if f.HasExpectedNumberActions() {
   106  				return true, f.Validate()
   107  			}
   108  			return false, nil
   109  		})
   110  	return err
   111  }
   112  
   113  func (f *recorderResourceManager) SetGroupVersionPriority(gv metav1.GroupVersion, grouppriority, versionpriority int) {
   114  	f.lock.Lock()
   115  	defer f.lock.Unlock()
   116  
   117  	f.Actions = append(f.Actions, recorderResourceManagerAction{
   118  		Type:    "SetGroupVersionPriority",
   119  		Group:   gv.Group,
   120  		Version: gv.Version,
   121  		Value:   versionpriority,
   122  	})
   123  }
   124  
   125  func (f *recorderResourceManager) AddGroupVersion(groupName string, value apidiscoveryv2.APIVersionDiscovery) {
   126  	f.lock.Lock()
   127  	defer f.lock.Unlock()
   128  
   129  	f.Actions = append(f.Actions, recorderResourceManagerAction{
   130  		Type:  "AddGroupVersion",
   131  		Group: groupName,
   132  		Value: value,
   133  	})
   134  }
   135  func (f *recorderResourceManager) RemoveGroup(groupName string) {
   136  	f.lock.Lock()
   137  	defer f.lock.Unlock()
   138  
   139  	f.Actions = append(f.Actions, recorderResourceManagerAction{
   140  		Type:  "RemoveGroup",
   141  		Group: groupName,
   142  	})
   143  
   144  }
   145  func (f *recorderResourceManager) RemoveGroupVersion(gv metav1.GroupVersion) {
   146  	f.lock.Lock()
   147  	defer f.lock.Unlock()
   148  
   149  	f.Actions = append(f.Actions, recorderResourceManagerAction{
   150  		Type:    "RemoveGroupVersion",
   151  		Group:   gv.Group,
   152  		Version: gv.Version,
   153  	})
   154  
   155  }
   156  func (f *recorderResourceManager) SetGroups(values []apidiscoveryv2.APIGroupDiscovery) {
   157  	f.lock.Lock()
   158  	defer f.lock.Unlock()
   159  
   160  	f.Actions = append(f.Actions, recorderResourceManagerAction{
   161  		Type:  "SetGroups",
   162  		Value: values,
   163  	})
   164  }
   165  func (f *recorderResourceManager) WebService() *restful.WebService {
   166  	panic("unimplemented")
   167  }
   168  
   169  func (f *recorderResourceManager) ServeHTTP(http.ResponseWriter, *http.Request) {
   170  	panic("unimplemented")
   171  }
   172  
   173  func (f *recorderResourceManager) WithSource(source Source) ResourceManager {
   174  	panic("unimplemented")
   175  }