//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
//

// Code generated by MockGen. DO NOT EDIT.
// Source: ./cloudstack/InternalLBService.go
//
// Generated by this command:
//
//	mockgen -destination=./cloudstack/InternalLBService_mock.go -package=cloudstack -copyright_file=header.txt -source=./cloudstack/InternalLBService.go
//

// Package cloudstack is a generated GoMock package.
package cloudstack

import (
	reflect "reflect"

	gomock "go.uber.org/mock/gomock"
)

// MockInternalLBServiceIface is a mock of InternalLBServiceIface interface.
type MockInternalLBServiceIface struct {
	ctrl     *gomock.Controller
	recorder *MockInternalLBServiceIfaceMockRecorder
	isgomock struct{}
}

// MockInternalLBServiceIfaceMockRecorder is the mock recorder for MockInternalLBServiceIface.
type MockInternalLBServiceIfaceMockRecorder struct {
	mock *MockInternalLBServiceIface
}

// NewMockInternalLBServiceIface creates a new mock instance.
func NewMockInternalLBServiceIface(ctrl *gomock.Controller) *MockInternalLBServiceIface {
	mock := &MockInternalLBServiceIface{ctrl: ctrl}
	mock.recorder = &MockInternalLBServiceIfaceMockRecorder{mock}
	return mock
}

// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockInternalLBServiceIface) EXPECT() *MockInternalLBServiceIfaceMockRecorder {
	return m.recorder
}

// ConfigureInternalLoadBalancerElement mocks base method.
func (m *MockInternalLBServiceIface) ConfigureInternalLoadBalancerElement(p *ConfigureInternalLoadBalancerElementParams) (*InternalLoadBalancerElementResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ConfigureInternalLoadBalancerElement", p)
	ret0, _ := ret[0].(*InternalLoadBalancerElementResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// ConfigureInternalLoadBalancerElement indicates an expected call of ConfigureInternalLoadBalancerElement.
func (mr *MockInternalLBServiceIfaceMockRecorder) ConfigureInternalLoadBalancerElement(p any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConfigureInternalLoadBalancerElement", reflect.TypeOf((*MockInternalLBServiceIface)(nil).ConfigureInternalLoadBalancerElement), p)
}

// CreateInternalLoadBalancerElement mocks base method.
func (m *MockInternalLBServiceIface) CreateInternalLoadBalancerElement(p *CreateInternalLoadBalancerElementParams) (*CreateInternalLoadBalancerElementResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "CreateInternalLoadBalancerElement", p)
	ret0, _ := ret[0].(*CreateInternalLoadBalancerElementResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// CreateInternalLoadBalancerElement indicates an expected call of CreateInternalLoadBalancerElement.
func (mr *MockInternalLBServiceIfaceMockRecorder) CreateInternalLoadBalancerElement(p any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateInternalLoadBalancerElement", reflect.TypeOf((*MockInternalLBServiceIface)(nil).CreateInternalLoadBalancerElement), p)
}

// GetInternalLoadBalancerElementByID mocks base method.
func (m *MockInternalLBServiceIface) GetInternalLoadBalancerElementByID(id string, opts ...OptionFunc) (*InternalLoadBalancerElement, int, error) {
	m.ctrl.T.Helper()
	varargs := []any{id}
	for _, a := range opts {
		varargs = append(varargs, a)
	}
	ret := m.ctrl.Call(m, "GetInternalLoadBalancerElementByID", varargs...)
	ret0, _ := ret[0].(*InternalLoadBalancerElement)
	ret1, _ := ret[1].(int)
	ret2, _ := ret[2].(error)
	return ret0, ret1, ret2
}

// GetInternalLoadBalancerElementByID indicates an expected call of GetInternalLoadBalancerElementByID.
func (mr *MockInternalLBServiceIfaceMockRecorder) GetInternalLoadBalancerElementByID(id any, opts ...any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	varargs := append([]any{id}, opts...)
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetInternalLoadBalancerElementByID", reflect.TypeOf((*MockInternalLBServiceIface)(nil).GetInternalLoadBalancerElementByID), varargs...)
}

// GetInternalLoadBalancerVMByID mocks base method.
func (m *MockInternalLBServiceIface) GetInternalLoadBalancerVMByID(id string, opts ...OptionFunc) (*InternalLoadBalancerVM, int, error) {
	m.ctrl.T.Helper()
	varargs := []any{id}
	for _, a := range opts {
		varargs = append(varargs, a)
	}
	ret := m.ctrl.Call(m, "GetInternalLoadBalancerVMByID", varargs...)
	ret0, _ := ret[0].(*InternalLoadBalancerVM)
	ret1, _ := ret[1].(int)
	ret2, _ := ret[2].(error)
	return ret0, ret1, ret2
}

// GetInternalLoadBalancerVMByID indicates an expected call of GetInternalLoadBalancerVMByID.
func (mr *MockInternalLBServiceIfaceMockRecorder) GetInternalLoadBalancerVMByID(id any, opts ...any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	varargs := append([]any{id}, opts...)
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetInternalLoadBalancerVMByID", reflect.TypeOf((*MockInternalLBServiceIface)(nil).GetInternalLoadBalancerVMByID), varargs...)
}

// GetInternalLoadBalancerVMByName mocks base method.
func (m *MockInternalLBServiceIface) GetInternalLoadBalancerVMByName(name string, opts ...OptionFunc) (*InternalLoadBalancerVM, int, error) {
	m.ctrl.T.Helper()
	varargs := []any{name}
	for _, a := range opts {
		varargs = append(varargs, a)
	}
	ret := m.ctrl.Call(m, "GetInternalLoadBalancerVMByName", varargs...)
	ret0, _ := ret[0].(*InternalLoadBalancerVM)
	ret1, _ := ret[1].(int)
	ret2, _ := ret[2].(error)
	return ret0, ret1, ret2
}

// GetInternalLoadBalancerVMByName indicates an expected call of GetInternalLoadBalancerVMByName.
func (mr *MockInternalLBServiceIfaceMockRecorder) GetInternalLoadBalancerVMByName(name any, opts ...any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	varargs := append([]any{name}, opts...)
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetInternalLoadBalancerVMByName", reflect.TypeOf((*MockInternalLBServiceIface)(nil).GetInternalLoadBalancerVMByName), varargs...)
}

// GetInternalLoadBalancerVMID mocks base method.
func (m *MockInternalLBServiceIface) GetInternalLoadBalancerVMID(name string, opts ...OptionFunc) (string, int, error) {
	m.ctrl.T.Helper()
	varargs := []any{name}
	for _, a := range opts {
		varargs = append(varargs, a)
	}
	ret := m.ctrl.Call(m, "GetInternalLoadBalancerVMID", varargs...)
	ret0, _ := ret[0].(string)
	ret1, _ := ret[1].(int)
	ret2, _ := ret[2].(error)
	return ret0, ret1, ret2
}

// GetInternalLoadBalancerVMID indicates an expected call of GetInternalLoadBalancerVMID.
func (mr *MockInternalLBServiceIfaceMockRecorder) GetInternalLoadBalancerVMID(name any, opts ...any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	varargs := append([]any{name}, opts...)
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetInternalLoadBalancerVMID", reflect.TypeOf((*MockInternalLBServiceIface)(nil).GetInternalLoadBalancerVMID), varargs...)
}

// ListInternalLoadBalancerElements mocks base method.
func (m *MockInternalLBServiceIface) ListInternalLoadBalancerElements(p *ListInternalLoadBalancerElementsParams) (*ListInternalLoadBalancerElementsResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListInternalLoadBalancerElements", p)
	ret0, _ := ret[0].(*ListInternalLoadBalancerElementsResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// ListInternalLoadBalancerElements indicates an expected call of ListInternalLoadBalancerElements.
func (mr *MockInternalLBServiceIfaceMockRecorder) ListInternalLoadBalancerElements(p any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListInternalLoadBalancerElements", reflect.TypeOf((*MockInternalLBServiceIface)(nil).ListInternalLoadBalancerElements), p)
}

// ListInternalLoadBalancerVMs mocks base method.
func (m *MockInternalLBServiceIface) ListInternalLoadBalancerVMs(p *ListInternalLoadBalancerVMsParams) (*ListInternalLoadBalancerVMsResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListInternalLoadBalancerVMs", p)
	ret0, _ := ret[0].(*ListInternalLoadBalancerVMsResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// ListInternalLoadBalancerVMs indicates an expected call of ListInternalLoadBalancerVMs.
func (mr *MockInternalLBServiceIfaceMockRecorder) ListInternalLoadBalancerVMs(p any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListInternalLoadBalancerVMs", reflect.TypeOf((*MockInternalLBServiceIface)(nil).ListInternalLoadBalancerVMs), p)
}

// NewConfigureInternalLoadBalancerElementParams mocks base method.
func (m *MockInternalLBServiceIface) NewConfigureInternalLoadBalancerElementParams(enabled bool, id string) *ConfigureInternalLoadBalancerElementParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewConfigureInternalLoadBalancerElementParams", enabled, id)
	ret0, _ := ret[0].(*ConfigureInternalLoadBalancerElementParams)
	return ret0
}

// NewConfigureInternalLoadBalancerElementParams indicates an expected call of NewConfigureInternalLoadBalancerElementParams.
func (mr *MockInternalLBServiceIfaceMockRecorder) NewConfigureInternalLoadBalancerElementParams(enabled, id any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewConfigureInternalLoadBalancerElementParams", reflect.TypeOf((*MockInternalLBServiceIface)(nil).NewConfigureInternalLoadBalancerElementParams), enabled, id)
}

// NewCreateInternalLoadBalancerElementParams mocks base method.
func (m *MockInternalLBServiceIface) NewCreateInternalLoadBalancerElementParams(nspid string) *CreateInternalLoadBalancerElementParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewCreateInternalLoadBalancerElementParams", nspid)
	ret0, _ := ret[0].(*CreateInternalLoadBalancerElementParams)
	return ret0
}

// NewCreateInternalLoadBalancerElementParams indicates an expected call of NewCreateInternalLoadBalancerElementParams.
func (mr *MockInternalLBServiceIfaceMockRecorder) NewCreateInternalLoadBalancerElementParams(nspid any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewCreateInternalLoadBalancerElementParams", reflect.TypeOf((*MockInternalLBServiceIface)(nil).NewCreateInternalLoadBalancerElementParams), nspid)
}

// NewListInternalLoadBalancerElementsParams mocks base method.
func (m *MockInternalLBServiceIface) NewListInternalLoadBalancerElementsParams() *ListInternalLoadBalancerElementsParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewListInternalLoadBalancerElementsParams")
	ret0, _ := ret[0].(*ListInternalLoadBalancerElementsParams)
	return ret0
}

// NewListInternalLoadBalancerElementsParams indicates an expected call of NewListInternalLoadBalancerElementsParams.
func (mr *MockInternalLBServiceIfaceMockRecorder) NewListInternalLoadBalancerElementsParams() *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewListInternalLoadBalancerElementsParams", reflect.TypeOf((*MockInternalLBServiceIface)(nil).NewListInternalLoadBalancerElementsParams))
}

// NewListInternalLoadBalancerVMsParams mocks base method.
func (m *MockInternalLBServiceIface) NewListInternalLoadBalancerVMsParams() *ListInternalLoadBalancerVMsParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewListInternalLoadBalancerVMsParams")
	ret0, _ := ret[0].(*ListInternalLoadBalancerVMsParams)
	return ret0
}

// NewListInternalLoadBalancerVMsParams indicates an expected call of NewListInternalLoadBalancerVMsParams.
func (mr *MockInternalLBServiceIfaceMockRecorder) NewListInternalLoadBalancerVMsParams() *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewListInternalLoadBalancerVMsParams", reflect.TypeOf((*MockInternalLBServiceIface)(nil).NewListInternalLoadBalancerVMsParams))
}

// NewStartInternalLoadBalancerVMParams mocks base method.
func (m *MockInternalLBServiceIface) NewStartInternalLoadBalancerVMParams(id string) *StartInternalLoadBalancerVMParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewStartInternalLoadBalancerVMParams", id)
	ret0, _ := ret[0].(*StartInternalLoadBalancerVMParams)
	return ret0
}

// NewStartInternalLoadBalancerVMParams indicates an expected call of NewStartInternalLoadBalancerVMParams.
func (mr *MockInternalLBServiceIfaceMockRecorder) NewStartInternalLoadBalancerVMParams(id any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewStartInternalLoadBalancerVMParams", reflect.TypeOf((*MockInternalLBServiceIface)(nil).NewStartInternalLoadBalancerVMParams), id)
}

// NewStopInternalLoadBalancerVMParams mocks base method.
func (m *MockInternalLBServiceIface) NewStopInternalLoadBalancerVMParams(id string) *StopInternalLoadBalancerVMParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewStopInternalLoadBalancerVMParams", id)
	ret0, _ := ret[0].(*StopInternalLoadBalancerVMParams)
	return ret0
}

// NewStopInternalLoadBalancerVMParams indicates an expected call of NewStopInternalLoadBalancerVMParams.
func (mr *MockInternalLBServiceIfaceMockRecorder) NewStopInternalLoadBalancerVMParams(id any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewStopInternalLoadBalancerVMParams", reflect.TypeOf((*MockInternalLBServiceIface)(nil).NewStopInternalLoadBalancerVMParams), id)
}

// StartInternalLoadBalancerVM mocks base method.
func (m *MockInternalLBServiceIface) StartInternalLoadBalancerVM(p *StartInternalLoadBalancerVMParams) (*StartInternalLoadBalancerVMResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "StartInternalLoadBalancerVM", p)
	ret0, _ := ret[0].(*StartInternalLoadBalancerVMResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// StartInternalLoadBalancerVM indicates an expected call of StartInternalLoadBalancerVM.
func (mr *MockInternalLBServiceIfaceMockRecorder) StartInternalLoadBalancerVM(p any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartInternalLoadBalancerVM", reflect.TypeOf((*MockInternalLBServiceIface)(nil).StartInternalLoadBalancerVM), p)
}

// StopInternalLoadBalancerVM mocks base method.
func (m *MockInternalLBServiceIface) StopInternalLoadBalancerVM(p *StopInternalLoadBalancerVMParams) (*StopInternalLoadBalancerVMResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "StopInternalLoadBalancerVM", p)
	ret0, _ := ret[0].(*StopInternalLoadBalancerVMResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// StopInternalLoadBalancerVM indicates an expected call of StopInternalLoadBalancerVM.
func (mr *MockInternalLBServiceIfaceMockRecorder) StopInternalLoadBalancerVM(p any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StopInternalLoadBalancerVM", reflect.TypeOf((*MockInternalLBServiceIface)(nil).StopInternalLoadBalancerVM), p)
}
