//
// 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/OvsElementService.go
//
// Generated by this command:
//
//	mockgen -destination=./cloudstack/OvsElementService_mock.go -package=cloudstack -copyright_file=header.txt -source=./cloudstack/OvsElementService.go
//

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

import (
	reflect "reflect"

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

// MockOvsElementServiceIface is a mock of OvsElementServiceIface interface.
type MockOvsElementServiceIface struct {
	ctrl     *gomock.Controller
	recorder *MockOvsElementServiceIfaceMockRecorder
	isgomock struct{}
}

// MockOvsElementServiceIfaceMockRecorder is the mock recorder for MockOvsElementServiceIface.
type MockOvsElementServiceIfaceMockRecorder struct {
	mock *MockOvsElementServiceIface
}

// NewMockOvsElementServiceIface creates a new mock instance.
func NewMockOvsElementServiceIface(ctrl *gomock.Controller) *MockOvsElementServiceIface {
	mock := &MockOvsElementServiceIface{ctrl: ctrl}
	mock.recorder = &MockOvsElementServiceIfaceMockRecorder{mock}
	return mock
}

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

// ConfigureOvsElement mocks base method.
func (m *MockOvsElementServiceIface) ConfigureOvsElement(p *ConfigureOvsElementParams) (*OvsElementResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ConfigureOvsElement", p)
	ret0, _ := ret[0].(*OvsElementResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

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

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

// ListOvsElements mocks base method.
func (m *MockOvsElementServiceIface) ListOvsElements(p *ListOvsElementsParams) (*ListOvsElementsResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListOvsElements", p)
	ret0, _ := ret[0].(*ListOvsElementsResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

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

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

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

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