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

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

import (
	reflect "reflect"

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

// MockUCSServiceIface is a mock of UCSServiceIface interface.
type MockUCSServiceIface struct {
	ctrl     *gomock.Controller
	recorder *MockUCSServiceIfaceMockRecorder
	isgomock struct{}
}

// MockUCSServiceIfaceMockRecorder is the mock recorder for MockUCSServiceIface.
type MockUCSServiceIfaceMockRecorder struct {
	mock *MockUCSServiceIface
}

// NewMockUCSServiceIface creates a new mock instance.
func NewMockUCSServiceIface(ctrl *gomock.Controller) *MockUCSServiceIface {
	mock := &MockUCSServiceIface{ctrl: ctrl}
	mock.recorder = &MockUCSServiceIfaceMockRecorder{mock}
	return mock
}

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

// AddUcsManager mocks base method.
func (m *MockUCSServiceIface) AddUcsManager(p *AddUcsManagerParams) (*AddUcsManagerResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "AddUcsManager", p)
	ret0, _ := ret[0].(*AddUcsManagerResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// AssociateUcsProfileToBlade mocks base method.
func (m *MockUCSServiceIface) AssociateUcsProfileToBlade(p *AssociateUcsProfileToBladeParams) (*AssociateUcsProfileToBladeResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "AssociateUcsProfileToBlade", p)
	ret0, _ := ret[0].(*AssociateUcsProfileToBladeResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// DeleteUcsManager mocks base method.
func (m *MockUCSServiceIface) DeleteUcsManager(p *DeleteUcsManagerParams) (*DeleteUcsManagerResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "DeleteUcsManager", p)
	ret0, _ := ret[0].(*DeleteUcsManagerResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

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

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

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

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

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

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

// ListUcsBlades mocks base method.
func (m *MockUCSServiceIface) ListUcsBlades(p *ListUcsBladesParams) (*ListUcsBladesResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListUcsBlades", p)
	ret0, _ := ret[0].(*ListUcsBladesResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// ListUcsManagers mocks base method.
func (m *MockUCSServiceIface) ListUcsManagers(p *ListUcsManagersParams) (*ListUcsManagersResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListUcsManagers", p)
	ret0, _ := ret[0].(*ListUcsManagersResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// ListUcsProfiles mocks base method.
func (m *MockUCSServiceIface) ListUcsProfiles(p *ListUcsProfilesParams) (*ListUcsProfilesResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListUcsProfiles", p)
	ret0, _ := ret[0].(*ListUcsProfilesResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// NewAddUcsManagerParams mocks base method.
func (m *MockUCSServiceIface) NewAddUcsManagerParams(password, url, username, zoneid string) *AddUcsManagerParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewAddUcsManagerParams", password, url, username, zoneid)
	ret0, _ := ret[0].(*AddUcsManagerParams)
	return ret0
}

// NewAddUcsManagerParams indicates an expected call of NewAddUcsManagerParams.
func (mr *MockUCSServiceIfaceMockRecorder) NewAddUcsManagerParams(password, url, username, zoneid any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewAddUcsManagerParams", reflect.TypeOf((*MockUCSServiceIface)(nil).NewAddUcsManagerParams), password, url, username, zoneid)
}

// NewAssociateUcsProfileToBladeParams mocks base method.
func (m *MockUCSServiceIface) NewAssociateUcsProfileToBladeParams(bladeid, profiledn, ucsmanagerid string) *AssociateUcsProfileToBladeParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewAssociateUcsProfileToBladeParams", bladeid, profiledn, ucsmanagerid)
	ret0, _ := ret[0].(*AssociateUcsProfileToBladeParams)
	return ret0
}

// NewAssociateUcsProfileToBladeParams indicates an expected call of NewAssociateUcsProfileToBladeParams.
func (mr *MockUCSServiceIfaceMockRecorder) NewAssociateUcsProfileToBladeParams(bladeid, profiledn, ucsmanagerid any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewAssociateUcsProfileToBladeParams", reflect.TypeOf((*MockUCSServiceIface)(nil).NewAssociateUcsProfileToBladeParams), bladeid, profiledn, ucsmanagerid)
}

// NewDeleteUcsManagerParams mocks base method.
func (m *MockUCSServiceIface) NewDeleteUcsManagerParams(ucsmanagerid string) *DeleteUcsManagerParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewDeleteUcsManagerParams", ucsmanagerid)
	ret0, _ := ret[0].(*DeleteUcsManagerParams)
	return ret0
}

// NewDeleteUcsManagerParams indicates an expected call of NewDeleteUcsManagerParams.
func (mr *MockUCSServiceIfaceMockRecorder) NewDeleteUcsManagerParams(ucsmanagerid any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewDeleteUcsManagerParams", reflect.TypeOf((*MockUCSServiceIface)(nil).NewDeleteUcsManagerParams), ucsmanagerid)
}

// NewListUcsBladesParams mocks base method.
func (m *MockUCSServiceIface) NewListUcsBladesParams(ucsmanagerid string) *ListUcsBladesParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewListUcsBladesParams", ucsmanagerid)
	ret0, _ := ret[0].(*ListUcsBladesParams)
	return ret0
}

// NewListUcsBladesParams indicates an expected call of NewListUcsBladesParams.
func (mr *MockUCSServiceIfaceMockRecorder) NewListUcsBladesParams(ucsmanagerid any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewListUcsBladesParams", reflect.TypeOf((*MockUCSServiceIface)(nil).NewListUcsBladesParams), ucsmanagerid)
}

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

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

// NewListUcsProfilesParams mocks base method.
func (m *MockUCSServiceIface) NewListUcsProfilesParams(ucsmanagerid string) *ListUcsProfilesParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewListUcsProfilesParams", ucsmanagerid)
	ret0, _ := ret[0].(*ListUcsProfilesParams)
	return ret0
}

// NewListUcsProfilesParams indicates an expected call of NewListUcsProfilesParams.
func (mr *MockUCSServiceIfaceMockRecorder) NewListUcsProfilesParams(ucsmanagerid any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewListUcsProfilesParams", reflect.TypeOf((*MockUCSServiceIface)(nil).NewListUcsProfilesParams), ucsmanagerid)
}
