//
// 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/ConfigurationService.go

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

import (
	reflect "reflect"

	gomock "github.com/golang/mock/gomock"
)

// MockConfigurationServiceIface is a mock of ConfigurationServiceIface interface.
type MockConfigurationServiceIface struct {
	ctrl     *gomock.Controller
	recorder *MockConfigurationServiceIfaceMockRecorder
}

// MockConfigurationServiceIfaceMockRecorder is the mock recorder for MockConfigurationServiceIface.
type MockConfigurationServiceIfaceMockRecorder struct {
	mock *MockConfigurationServiceIface
}

// NewMockConfigurationServiceIface creates a new mock instance.
func NewMockConfigurationServiceIface(ctrl *gomock.Controller) *MockConfigurationServiceIface {
	mock := &MockConfigurationServiceIface{ctrl: ctrl}
	mock.recorder = &MockConfigurationServiceIfaceMockRecorder{mock}
	return mock
}

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

// ListCapabilities mocks base method.
func (m *MockConfigurationServiceIface) ListCapabilities(p *ListCapabilitiesParams) (*ListCapabilitiesResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListCapabilities", p)
	ret0, _ := ret[0].(*ListCapabilitiesResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// ListCapabilities indicates an expected call of ListCapabilities.
func (mr *MockConfigurationServiceIfaceMockRecorder) ListCapabilities(p interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListCapabilities", reflect.TypeOf((*MockConfigurationServiceIface)(nil).ListCapabilities), p)
}

// ListConfigurations mocks base method.
func (m *MockConfigurationServiceIface) ListConfigurations(p *ListConfigurationsParams) (*ListConfigurationsResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListConfigurations", p)
	ret0, _ := ret[0].(*ListConfigurationsResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// ListConfigurations indicates an expected call of ListConfigurations.
func (mr *MockConfigurationServiceIfaceMockRecorder) ListConfigurations(p interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListConfigurations", reflect.TypeOf((*MockConfigurationServiceIface)(nil).ListConfigurations), p)
}

// ListDeploymentPlanners mocks base method.
func (m *MockConfigurationServiceIface) ListDeploymentPlanners(p *ListDeploymentPlannersParams) (*ListDeploymentPlannersResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListDeploymentPlanners", p)
	ret0, _ := ret[0].(*ListDeploymentPlannersResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// ListDeploymentPlanners indicates an expected call of ListDeploymentPlanners.
func (mr *MockConfigurationServiceIfaceMockRecorder) ListDeploymentPlanners(p interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListDeploymentPlanners", reflect.TypeOf((*MockConfigurationServiceIface)(nil).ListDeploymentPlanners), p)
}

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

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

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

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

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

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

// NewUpdateConfigurationParams mocks base method.
func (m *MockConfigurationServiceIface) NewUpdateConfigurationParams(name string) *UpdateConfigurationParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewUpdateConfigurationParams", name)
	ret0, _ := ret[0].(*UpdateConfigurationParams)
	return ret0
}

// NewUpdateConfigurationParams indicates an expected call of NewUpdateConfigurationParams.
func (mr *MockConfigurationServiceIfaceMockRecorder) NewUpdateConfigurationParams(name interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewUpdateConfigurationParams", reflect.TypeOf((*MockConfigurationServiceIface)(nil).NewUpdateConfigurationParams), name)
}

// UpdateConfiguration mocks base method.
func (m *MockConfigurationServiceIface) UpdateConfiguration(p *UpdateConfigurationParams) (*UpdateConfigurationResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "UpdateConfiguration", p)
	ret0, _ := ret[0].(*UpdateConfigurationResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// UpdateConfiguration indicates an expected call of UpdateConfiguration.
func (mr *MockConfigurationServiceIfaceMockRecorder) UpdateConfiguration(p interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConfiguration", reflect.TypeOf((*MockConfigurationServiceIface)(nil).UpdateConfiguration), p)
}
