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

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

import (
	reflect "reflect"

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

// MockAddressServiceIface is a mock of AddressServiceIface interface.
type MockAddressServiceIface struct {
	ctrl     *gomock.Controller
	recorder *MockAddressServiceIfaceMockRecorder
	isgomock struct{}
}

// MockAddressServiceIfaceMockRecorder is the mock recorder for MockAddressServiceIface.
type MockAddressServiceIfaceMockRecorder struct {
	mock *MockAddressServiceIface
}

// NewMockAddressServiceIface creates a new mock instance.
func NewMockAddressServiceIface(ctrl *gomock.Controller) *MockAddressServiceIface {
	mock := &MockAddressServiceIface{ctrl: ctrl}
	mock.recorder = &MockAddressServiceIfaceMockRecorder{mock}
	return mock
}

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

// AcquirePodIpAddress mocks base method.
func (m *MockAddressServiceIface) AcquirePodIpAddress(p *AcquirePodIpAddressParams) (*AcquirePodIpAddressResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "AcquirePodIpAddress", p)
	ret0, _ := ret[0].(*AcquirePodIpAddressResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// AssociateIpAddress mocks base method.
func (m *MockAddressServiceIface) AssociateIpAddress(p *AssociateIpAddressParams) (*AssociateIpAddressResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "AssociateIpAddress", p)
	ret0, _ := ret[0].(*AssociateIpAddressResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// DisassociateIpAddress mocks base method.
func (m *MockAddressServiceIface) DisassociateIpAddress(p *DisassociateIpAddressParams) (*DisassociateIpAddressResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "DisassociateIpAddress", p)
	ret0, _ := ret[0].(*DisassociateIpAddressResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

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

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

// ListPublicIpAddresses mocks base method.
func (m *MockAddressServiceIface) ListPublicIpAddresses(p *ListPublicIpAddressesParams) (*ListPublicIpAddressesResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListPublicIpAddresses", p)
	ret0, _ := ret[0].(*ListPublicIpAddressesResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// NewAcquirePodIpAddressParams mocks base method.
func (m *MockAddressServiceIface) NewAcquirePodIpAddressParams(zoneid string) *AcquirePodIpAddressParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewAcquirePodIpAddressParams", zoneid)
	ret0, _ := ret[0].(*AcquirePodIpAddressParams)
	return ret0
}

// NewAcquirePodIpAddressParams indicates an expected call of NewAcquirePodIpAddressParams.
func (mr *MockAddressServiceIfaceMockRecorder) NewAcquirePodIpAddressParams(zoneid any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewAcquirePodIpAddressParams", reflect.TypeOf((*MockAddressServiceIface)(nil).NewAcquirePodIpAddressParams), zoneid)
}

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

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

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

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

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

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

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

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

// NewReleasePodIpAddressParams mocks base method.
func (m *MockAddressServiceIface) NewReleasePodIpAddressParams(id int64) *ReleasePodIpAddressParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewReleasePodIpAddressParams", id)
	ret0, _ := ret[0].(*ReleasePodIpAddressParams)
	return ret0
}

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

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

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

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

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

// ReleaseIpAddress mocks base method.
func (m *MockAddressServiceIface) ReleaseIpAddress(p *ReleaseIpAddressParams) (*ReleaseIpAddressResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ReleaseIpAddress", p)
	ret0, _ := ret[0].(*ReleaseIpAddressResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// ReleasePodIpAddress mocks base method.
func (m *MockAddressServiceIface) ReleasePodIpAddress(p *ReleasePodIpAddressParams) (*ReleasePodIpAddressResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ReleasePodIpAddress", p)
	ret0, _ := ret[0].(*ReleasePodIpAddressResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// ReserveIpAddress mocks base method.
func (m *MockAddressServiceIface) ReserveIpAddress(p *ReserveIpAddressParams) (*ReserveIpAddressResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ReserveIpAddress", p)
	ret0, _ := ret[0].(*ReserveIpAddressResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// UpdateIpAddress mocks base method.
func (m *MockAddressServiceIface) UpdateIpAddress(p *UpdateIpAddressParams) (*UpdateIpAddressResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "UpdateIpAddress", p)
	ret0, _ := ret[0].(*UpdateIpAddressResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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