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

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

import (
	reflect "reflect"

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

// MockNetrisServiceIface is a mock of NetrisServiceIface interface.
type MockNetrisServiceIface struct {
	ctrl     *gomock.Controller
	recorder *MockNetrisServiceIfaceMockRecorder
	isgomock struct{}
}

// MockNetrisServiceIfaceMockRecorder is the mock recorder for MockNetrisServiceIface.
type MockNetrisServiceIfaceMockRecorder struct {
	mock *MockNetrisServiceIface
}

// NewMockNetrisServiceIface creates a new mock instance.
func NewMockNetrisServiceIface(ctrl *gomock.Controller) *MockNetrisServiceIface {
	mock := &MockNetrisServiceIface{ctrl: ctrl}
	mock.recorder = &MockNetrisServiceIfaceMockRecorder{mock}
	return mock
}

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

// AddNetrisProvider mocks base method.
func (m *MockNetrisServiceIface) AddNetrisProvider(p *AddNetrisProviderParams) (*AddNetrisProviderResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "AddNetrisProvider", p)
	ret0, _ := ret[0].(*AddNetrisProviderResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// DeleteNetrisProvider mocks base method.
func (m *MockNetrisServiceIface) DeleteNetrisProvider(p *DeleteNetrisProviderParams) (*DeleteNetrisProviderResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "DeleteNetrisProvider", p)
	ret0, _ := ret[0].(*DeleteNetrisProviderResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// ListNetrisProviders mocks base method.
func (m *MockNetrisServiceIface) ListNetrisProviders(p *ListNetrisProvidersParams) (*ListNetrisProvidersResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListNetrisProviders", p)
	ret0, _ := ret[0].(*ListNetrisProvidersResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// NewAddNetrisProviderParams mocks base method.
func (m *MockNetrisServiceIface) NewAddNetrisProviderParams(name, netristag, netrisurl, password, sitename, tenantname, username, zoneid string) *AddNetrisProviderParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewAddNetrisProviderParams", name, netristag, netrisurl, password, sitename, tenantname, username, zoneid)
	ret0, _ := ret[0].(*AddNetrisProviderParams)
	return ret0
}

// NewAddNetrisProviderParams indicates an expected call of NewAddNetrisProviderParams.
func (mr *MockNetrisServiceIfaceMockRecorder) NewAddNetrisProviderParams(name, netristag, netrisurl, password, sitename, tenantname, username, zoneid any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewAddNetrisProviderParams", reflect.TypeOf((*MockNetrisServiceIface)(nil).NewAddNetrisProviderParams), name, netristag, netrisurl, password, sitename, tenantname, username, zoneid)
}

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

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

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

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