cns/fakes/cnsfake.go (230 lines of code) (raw):

//go:build !ignore_uncovered // +build !ignore_uncovered package fakes import ( "context" "encoding/json" "errors" "sync" "time" "github.com/Azure/azure-container-networking/cns" "github.com/Azure/azure-container-networking/cns/common" "github.com/Azure/azure-container-networking/cns/types" ) type StringStack struct { sync.Mutex items []string } func NewStack() *StringStack { return &StringStack{items: make([]string, 0)} } func (stack *StringStack) Push(v string) { stack.Lock() defer stack.Unlock() stack.items = append(stack.items, v) } func (stack *StringStack) Pop() (string, error) { stack.Lock() defer stack.Unlock() length := len(stack.items) if length == 0 { return "", errors.New("Empty Stack") } res := stack.items[length-1] stack.items = stack.items[:length-1] return res, nil } type IPStateManager struct { PendingProgramIPConfigState map[string]cns.IPConfigurationStatus AvailableIPConfigState map[string]cns.IPConfigurationStatus AssignedIPConfigState map[string]cns.IPConfigurationStatus PendingReleaseIPConfigState map[string]cns.IPConfigurationStatus AvailableIPIDStack StringStack sync.RWMutex } func NewIPStateManager() IPStateManager { return IPStateManager{ PendingProgramIPConfigState: make(map[string]cns.IPConfigurationStatus), AvailableIPConfigState: make(map[string]cns.IPConfigurationStatus), AssignedIPConfigState: make(map[string]cns.IPConfigurationStatus), PendingReleaseIPConfigState: make(map[string]cns.IPConfigurationStatus), AvailableIPIDStack: StringStack{}, } } func (ipm *IPStateManager) AddIPConfigs(ipconfigs []cns.IPConfigurationStatus) { ipm.Lock() defer ipm.Unlock() for _, ipconfig := range ipconfigs { switch ipconfig.GetState() { case types.PendingProgramming: ipm.PendingProgramIPConfigState[ipconfig.ID] = ipconfig case types.Available: ipm.AvailableIPConfigState[ipconfig.ID] = ipconfig ipm.AvailableIPIDStack.Push(ipconfig.ID) case types.Assigned: ipm.AssignedIPConfigState[ipconfig.ID] = ipconfig case types.PendingRelease: ipm.PendingReleaseIPConfigState[ipconfig.ID] = ipconfig } } } func (ipm *IPStateManager) RemovePendingReleaseIPConfigs(ipconfigNames []string) { ipm.Lock() defer ipm.Unlock() for _, name := range ipconfigNames { delete(ipm.PendingReleaseIPConfigState, name) } } func (ipm *IPStateManager) ReserveIPConfig() (cns.IPConfigurationStatus, error) { ipm.Lock() defer ipm.Unlock() id, err := ipm.AvailableIPIDStack.Pop() if err != nil { return cns.IPConfigurationStatus{}, err } ipc := ipm.AvailableIPConfigState[id] ipc.SetState(types.Assigned) ipm.AssignedIPConfigState[id] = ipc delete(ipm.AvailableIPConfigState, id) return ipm.AssignedIPConfigState[id], nil } func (ipm *IPStateManager) ReleaseIPConfig(ipconfigID string) (cns.IPConfigurationStatus, error) { ipm.Lock() defer ipm.Unlock() ipc := ipm.AssignedIPConfigState[ipconfigID] ipc.SetState(types.Available) ipm.AvailableIPConfigState[ipconfigID] = ipc ipm.AvailableIPIDStack.Push(ipconfigID) delete(ipm.AssignedIPConfigState, ipconfigID) return ipm.AvailableIPConfigState[ipconfigID], nil } func (ipm *IPStateManager) MarkNIPsPendingRelease(n int) (map[string]cns.IPConfigurationStatus, error) { // MarkIPASPendingRelease actually already errors if it is unable to release all N IPs return ipm.MarkIPAsPendingRelease(n) } func (ipm *IPStateManager) MarkIPAsPendingRelease(numberOfIPsToMark int) (map[string]cns.IPConfigurationStatus, error) { ipm.Lock() defer ipm.Unlock() var err error pendingReleaseIPs := make(map[string]cns.IPConfigurationStatus) defer func() { // if there was an error, and not all ip's have been freed, restore state if err != nil && len(pendingReleaseIPs) != numberOfIPsToMark { for uuid, ipState := range pendingReleaseIPs { ipState.SetState(types.Available) ipm.AvailableIPIDStack.Push(pendingReleaseIPs[uuid].ID) ipm.AvailableIPConfigState[pendingReleaseIPs[uuid].ID] = ipState delete(ipm.PendingReleaseIPConfigState, pendingReleaseIPs[uuid].ID) } } }() for i := 0; i < numberOfIPsToMark; i++ { id, err := ipm.AvailableIPIDStack.Pop() if err != nil { return ipm.PendingReleaseIPConfigState, err } // add all pending release to a slice ipConfig := ipm.AvailableIPConfigState[id] ipConfig.SetState(types.PendingRelease) pendingReleaseIPs[id] = ipConfig delete(ipm.AvailableIPConfigState, id) } // if no errors at this point, add the pending ips to the Pending state for _, pendingReleaseIP := range pendingReleaseIPs { ipm.PendingReleaseIPConfigState[pendingReleaseIP.ID] = pendingReleaseIP } return pendingReleaseIPs, nil } var _ cns.HTTPService = (*HTTPServiceFake)(nil) type HTTPServiceFake struct { IPStateManager IPStateManager PoolMonitor cns.IPAMPoolMonitor } func NewHTTPServiceFake() *HTTPServiceFake { return &HTTPServiceFake{ IPStateManager: NewIPStateManager(), } } func (fake *HTTPServiceFake) SetNumberOfAssignedIPs(assign int) error { currentAssigned := len(fake.IPStateManager.AssignedIPConfigState) delta := (assign - currentAssigned) if delta > 0 { // assign IPs for i := 0; i < delta; i++ { if _, err := fake.IPStateManager.ReserveIPConfig(); err != nil { return err } } return nil } // unassign IPs delta *= -1 i := 0 for id := range fake.IPStateManager.AssignedIPConfigState { if i >= delta { break } if _, err := fake.IPStateManager.ReleaseIPConfig(id); err != nil { return err } i++ } return nil } func (fake *HTTPServiceFake) SendNCSnapShotPeriodically(context.Context, int) {} func (fake *HTTPServiceFake) SetNodeOrchestrator(*cns.SetOrchestratorTypeRequest) {} func (fake *HTTPServiceFake) SyncNodeStatus(string, string, string, json.RawMessage) (types.ResponseCode, string) { return 0, "" } // SyncHostNCVersion will update HostVersion in containerstatus. func (fake *HTTPServiceFake) SyncHostNCVersion(context.Context, string, time.Duration) {} func (fake *HTTPServiceFake) GetPendingProgramIPConfigs() []cns.IPConfigurationStatus { ipconfigs := []cns.IPConfigurationStatus{} for _, ipconfig := range fake.IPStateManager.PendingProgramIPConfigState { ipconfigs = append(ipconfigs, ipconfig) } return ipconfigs } func (fake *HTTPServiceFake) GetAvailableIPConfigs() []cns.IPConfigurationStatus { ipconfigs := []cns.IPConfigurationStatus{} for _, ipconfig := range fake.IPStateManager.AvailableIPConfigState { ipconfigs = append(ipconfigs, ipconfig) } return ipconfigs } func (fake *HTTPServiceFake) GetAssignedIPConfigs() []cns.IPConfigurationStatus { ipconfigs := []cns.IPConfigurationStatus{} for _, ipconfig := range fake.IPStateManager.AssignedIPConfigState { ipconfigs = append(ipconfigs, ipconfig) } return ipconfigs } func (fake *HTTPServiceFake) GetPendingReleaseIPConfigs() []cns.IPConfigurationStatus { ipconfigs := []cns.IPConfigurationStatus{} for _, ipconfig := range fake.IPStateManager.PendingReleaseIPConfigState { ipconfigs = append(ipconfigs, ipconfig) } return ipconfigs } // Return union of all state maps func (fake *HTTPServiceFake) GetPodIPConfigState() map[string]cns.IPConfigurationStatus { ipconfigs := make(map[string]cns.IPConfigurationStatus) for key, val := range fake.IPStateManager.AssignedIPConfigState { ipconfigs[key] = val } for key, val := range fake.IPStateManager.AvailableIPConfigState { ipconfigs[key] = val } for key, val := range fake.IPStateManager.PendingReleaseIPConfigState { ipconfigs[key] = val } return ipconfigs } func (fake *HTTPServiceFake) MarkNIPsPendingRelease(n int) (map[string]cns.IPConfigurationStatus, error) { return fake.IPStateManager.MarkIPAsPendingRelease(n) } // TODO: Populate on scale down func (fake *HTTPServiceFake) MarkIPAsPendingRelease(numberToMark int) (map[string]cns.IPConfigurationStatus, error) { return fake.IPStateManager.MarkIPAsPendingRelease(numberToMark) } func (fake *HTTPServiceFake) GetOption(string) interface{} { return nil } func (fake *HTTPServiceFake) SetOption(string, interface{}) {} func (fake *HTTPServiceFake) Start(*common.ServiceConfig) error { return nil } func (fake *HTTPServiceFake) Init(*common.ServiceConfig) error { return nil } func (fake *HTTPServiceFake) Stop() {} func (fake *HTTPServiceFake) AttachIPConfigsHandlerMiddleware(cns.IPConfigsHandlerMiddleware) {}