Add deletion interfaces for VM, VMSS and interface clients

This commit is contained in:
Pengfei Ni 2020-02-14 18:21:29 +08:00
parent 3273cd99b1
commit c1383e99af
13 changed files with 264 additions and 0 deletions

View File

@ -292,6 +292,10 @@ func (fIC *fakeAzureInterfacesClient) GetVirtualMachineScaleSetNetworkInterface(
errors.New("Not such Interface"))
}
func (fIC *fakeAzureInterfacesClient) Delete(ctx context.Context, resourceGroupName string, networkInterfaceName string) *retry.Error {
return nil
}
func (fIC *fakeAzureInterfacesClient) setFakeStore(store map[string]map[string]network.Interface) {
fIC.mutex.Lock()
defer fIC.mutex.Unlock()
@ -363,6 +367,10 @@ func (fVMC *fakeAzureVirtualMachinesClient) List(ctx context.Context, resourceGr
return result, nil
}
func (fVMC *fakeAzureVirtualMachinesClient) Delete(ctx context.Context, resourceGroupName string, VMName string) *retry.Error {
return nil
}
func (fVMC *fakeAzureVirtualMachinesClient) setFakeStore(store map[string]map[string]compute.VirtualMachine) {
fVMC.mutex.Lock()
defer fVMC.mutex.Unlock()
@ -661,6 +669,10 @@ func (fVMSSC *fakeVirtualMachineScaleSetsClient) UpdateInstances(ctx context.Con
return nil
}
func (fVMSSC *fakeVirtualMachineScaleSetsClient) DeleteInstances(ctx context.Context, resourceGroupName string, vmScaleSetName string, vmInstanceIDs compute.VirtualMachineScaleSetVMInstanceRequiredIDs) *retry.Error {
return nil
}
type fakeRoutesClient struct {
mutex *sync.Mutex
FakeStore map[string]map[string]network.Route

View File

@ -274,3 +274,46 @@ func (c *Client) createOrUpdateResponder(resp *http.Response) (*network.Interfac
result.Response = autorest.Response{Response: resp}
return result, retry.GetError(resp, err)
}
// Delete deletes a network interface by name.
func (c *Client) Delete(ctx context.Context, resourceGroupName string, networkInterfaceName string) *retry.Error {
mc := metrics.NewMetricContext("interfaces", "delete", resourceGroupName, c.subscriptionID, "")
// Report errors if the client is rate limited.
if !c.rateLimiterWriter.TryAccept() {
mc.RateLimitedCount()
return retry.GetRateLimitError(true, "NicDelete")
}
// Report errors if the client is throttled.
if c.RetryAfterWriter.After(time.Now()) {
mc.ThrottledCount()
rerr := retry.GetThrottlingError("NicDelete", "client throttled", c.RetryAfterWriter)
return rerr
}
rerr := c.deleteInterface(ctx, resourceGroupName, networkInterfaceName)
mc.Observe(rerr.Error())
if rerr != nil {
if rerr.IsThrottled() {
// Update RetryAfterReader so that no more requests would be sent until RetryAfter expires.
c.RetryAfterWriter = rerr.RetryAfter
}
return rerr
}
return nil
}
// deleteInterface deletes a network interface by name.
func (c *Client) deleteInterface(ctx context.Context, resourceGroupName string, networkInterfaceName string) *retry.Error {
resourceID := armclient.GetResourceID(
c.subscriptionID,
resourceGroupName,
"Microsoft.Network/networkInterfaces",
networkInterfaceName,
)
return c.armClient.DeleteResource(ctx, resourceID, "")
}

View File

@ -121,6 +121,19 @@ func TestCreateOrUpdate(t *testing.T) {
assert.Nil(t, rerr)
}
func TestDelete(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
r := getTestInterface("interface1")
armClient := mockarmclient.NewMockInterface(ctrl)
armClient.EXPECT().DeleteResource(gomock.Any(), to.String(r.ID), "").Return(nil).Times(1)
diskClient := getTestInterfaceClient(armClient)
rerr := diskClient.Delete(context.TODO(), "rg", "interface1")
assert.Nil(t, rerr)
}
func getTestInterface(name string) network.Interface {
resourceID := fmt.Sprintf("/subscriptions/subscriptionID/resourceGroups/rg/providers/Microsoft.Network/networkInterfaces/%s", name)
return network.Interface{

View File

@ -45,4 +45,7 @@ type Interface interface {
// CreateOrUpdate creates or updates a network.Interface.
CreateOrUpdate(ctx context.Context, resourceGroupName string, networkInterfaceName string, parameters network.Interface) *retry.Error
// Delete deletes a network interface by name.
Delete(ctx context.Context, resourceGroupName string, networkInterfaceName string) *retry.Error
}

View File

@ -93,3 +93,17 @@ func (mr *MockInterfaceMockRecorder) CreateOrUpdate(ctx, resourceGroupName, netw
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdate", reflect.TypeOf((*MockInterface)(nil).CreateOrUpdate), ctx, resourceGroupName, networkInterfaceName, parameters)
}
// Delete mocks base method
func (m *MockInterface) Delete(ctx context.Context, resourceGroupName, networkInterfaceName string) *retry.Error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Delete", ctx, resourceGroupName, networkInterfaceName)
ret0, _ := ret[0].(*retry.Error)
return ret0
}
// Delete indicates an expected call of Delete
func (mr *MockInterfaceMockRecorder) Delete(ctx, resourceGroupName, networkInterfaceName interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockInterface)(nil).Delete), ctx, resourceGroupName, networkInterfaceName)
}

View File

@ -434,3 +434,46 @@ func (c *Client) createOrUpdateResponder(resp *http.Response) (*compute.VirtualM
result.Response = autorest.Response{Response: resp}
return result, retry.GetError(resp, err)
}
// Delete deletes a VirtualMachine.
func (c *Client) Delete(ctx context.Context, resourceGroupName string, VMName string) *retry.Error {
mc := metrics.NewMetricContext("vm", "delete", resourceGroupName, c.subscriptionID, "")
// Report errors if the client is rate limited.
if !c.rateLimiterWriter.TryAccept() {
mc.RateLimitedCount()
return retry.GetRateLimitError(true, "VMDelete")
}
// Report errors if the client is throttled.
if c.RetryAfterWriter.After(time.Now()) {
mc.ThrottledCount()
rerr := retry.GetThrottlingError("VMDelete", "client throttled", c.RetryAfterWriter)
return rerr
}
rerr := c.deleteVM(ctx, resourceGroupName, VMName)
mc.Observe(rerr.Error())
if rerr != nil {
if rerr.IsThrottled() {
// Update RetryAfterReader so that no more requests would be sent until RetryAfter expires.
c.RetryAfterWriter = rerr.RetryAfter
}
return rerr
}
return nil
}
// deleteVM deletes a VirtualMachine.
func (c *Client) deleteVM(ctx context.Context, resourceGroupName string, VMName string) *retry.Error {
resourceID := armclient.GetResourceID(
c.subscriptionID,
resourceGroupName,
"Microsoft.Compute/virtualMachines",
VMName,
)
return c.armClient.DeleteResource(ctx, resourceID, "")
}

View File

@ -139,6 +139,19 @@ func TestCreateOrUpdate(t *testing.T) {
assert.Nil(t, rerr)
}
func TestDelete(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
r := getTestVM("vm1")
armClient := mockarmclient.NewMockInterface(ctrl)
armClient.EXPECT().DeleteResource(gomock.Any(), to.String(r.ID), "").Return(nil).Times(1)
client := getTestVMClient(armClient)
rerr := client.Delete(context.TODO(), "rg", "vm1")
assert.Nil(t, rerr)
}
func getTestVM(vmName string) compute.VirtualMachine {
resourceID := fmt.Sprintf("/subscriptions/subscriptionID/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/%s", vmName)
return compute.VirtualMachine{

View File

@ -45,4 +45,7 @@ type Interface interface {
// Update updates a VirtualMachine.
Update(ctx context.Context, resourceGroupName string, VMName string, parameters compute.VirtualMachineUpdate, source string) *retry.Error
// Delete deletes a VirtualMachine.
Delete(ctx context.Context, resourceGroupName string, VMName string) *retry.Error
}

View File

@ -107,3 +107,17 @@ func (mr *MockInterfaceMockRecorder) Update(ctx, resourceGroupName, VMName, para
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockInterface)(nil).Update), ctx, resourceGroupName, VMName, parameters, source)
}
// Delete mocks base method
func (m *MockInterface) Delete(ctx context.Context, resourceGroupName, VMName string) *retry.Error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Delete", ctx, resourceGroupName, VMName)
ret0, _ := ret[0].(*retry.Error)
return ret0
}
// Delete indicates an expected call of Delete
func (mr *MockInterfaceMockRecorder) Delete(ctx, resourceGroupName, VMName interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockInterface)(nil).Delete), ctx, resourceGroupName, VMName)
}

View File

@ -359,3 +359,69 @@ func (page VirtualMachineScaleSetListResultPage) Values() []compute.VirtualMachi
}
return *page.vmsslr.Value
}
// DeleteInstances deletes the instances for a VirtualMachineScaleSet.
func (c *Client) DeleteInstances(ctx context.Context, resourceGroupName string, vmScaleSetName string, vmInstanceIDs compute.VirtualMachineScaleSetVMInstanceRequiredIDs) *retry.Error {
mc := metrics.NewMetricContext("vmss", "delete_instances", resourceGroupName, c.subscriptionID, "")
// Report errors if the client is rate limited.
if !c.rateLimiterWriter.TryAccept() {
mc.RateLimitedCount()
return retry.GetRateLimitError(true, "VMSSDeleteInstances")
}
// Report errors if the client is throttled.
if c.RetryAfterWriter.After(time.Now()) {
mc.ThrottledCount()
rerr := retry.GetThrottlingError("VMSSDeleteInstances", "client throttled", c.RetryAfterWriter)
return rerr
}
rerr := c.deleteVMSSInstances(ctx, resourceGroupName, vmScaleSetName, vmInstanceIDs)
mc.Observe(rerr.Error())
if rerr != nil {
if rerr.IsThrottled() {
// Update RetryAfterReader so that no more requests would be sent until RetryAfter expires.
c.RetryAfterWriter = rerr.RetryAfter
}
return rerr
}
return nil
}
// deleteVMSSInstances deletes the instances for a VirtualMachineScaleSet.
func (c *Client) deleteVMSSInstances(ctx context.Context, resourceGroupName string, vmScaleSetName string, vmInstanceIDs compute.VirtualMachineScaleSetVMInstanceRequiredIDs) *retry.Error {
resourceID := armclient.GetResourceID(
c.subscriptionID,
resourceGroupName,
"Microsoft.Compute/virtualMachineScaleSets",
vmScaleSetName,
)
response, rerr := c.armClient.PostResource(ctx, resourceID, "delete", vmInstanceIDs)
defer c.armClient.CloseResponse(ctx, response)
if rerr != nil {
klog.V(5).Infof("Received error in %s: resourceID: %s, error: %s", "vmss.deletevms.request", resourceID, rerr.Error())
return rerr
}
err := autorest.Respond(response, azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusAccepted))
if err != nil {
klog.V(5).Infof("Received error in %s: resourceID: %s, error: %s", "vmss.deletevms.respond", resourceID, rerr.Error())
return retry.GetError(response, err)
}
future, err := azure.NewFutureFromResponse(response)
if err != nil {
klog.V(5).Infof("Received error in %s: resourceID: %s, error: %s", "vmss.deletevms.future", resourceID, rerr.Error())
return retry.NewError(false, err)
}
if err := c.armClient.WaitForAsyncOperationCompletion(ctx, &future, "vmssclient.DeleteInstances"); err != nil {
klog.V(5).Infof("Received error in %s: resourceID: %s, error: %s", "vmss.deletevms.wait", resourceID, rerr.Error())
return retry.NewError(false, err)
}
return nil
}

View File

@ -119,6 +119,29 @@ func TestCreateOrUpdate(t *testing.T) {
assert.Nil(t, rerr)
}
func TestDeleteInstances(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
r := getTestVMSS("vmss1")
vmInstanceIDs := compute.VirtualMachineScaleSetVMInstanceRequiredIDs{
InstanceIds: &[]string{"0", "1", "2"},
}
response := &http.Response{
StatusCode: http.StatusOK,
Request: &http.Request{Method: "POST"},
Body: ioutil.NopCloser(bytes.NewReader([]byte("{}"))),
}
armClient := mockarmclient.NewMockInterface(ctrl)
armClient.EXPECT().PostResource(gomock.Any(), to.String(r.ID), "delete", vmInstanceIDs).Return(response, nil).Times(1)
armClient.EXPECT().CloseResponse(gomock.Any(), gomock.Any()).Times(1)
armClient.EXPECT().WaitForAsyncOperationCompletion(gomock.Any(), gomock.Any(), "vmssclient.DeleteInstances").Return(nil).Times(1)
client := getTestVMSSClient(armClient)
rerr := client.DeleteInstances(context.TODO(), "rg", "vmss1", vmInstanceIDs)
assert.Nil(t, rerr)
}
func getTestVMSS(name string) compute.VirtualMachineScaleSet {
return compute.VirtualMachineScaleSet{
ID: to.StringPtr("/subscriptions/subscriptionID/resourceGroups/rg/providers/Microsoft.Compute/virtualMachineScaleSets/vmss1"),

View File

@ -42,4 +42,7 @@ type Interface interface {
// CreateOrUpdate creates or updates a VirtualMachineScaleSet.
CreateOrUpdate(ctx context.Context, resourceGroupName string, VMScaleSetName string, parameters compute.VirtualMachineScaleSet) *retry.Error
// DeleteInstances deletes the instances for a VirtualMachineScaleSet.
DeleteInstances(ctx context.Context, resourceGroupName string, vmScaleSetName string, vmInstanceIDs compute.VirtualMachineScaleSetVMInstanceRequiredIDs) *retry.Error
}

View File

@ -93,3 +93,17 @@ func (mr *MockInterfaceMockRecorder) CreateOrUpdate(ctx, resourceGroupName, VMSc
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdate", reflect.TypeOf((*MockInterface)(nil).CreateOrUpdate), ctx, resourceGroupName, VMScaleSetName, parameters)
}
// DeleteInstances mocks base method
func (m *MockInterface) DeleteInstances(ctx context.Context, resourceGroupName, vmScaleSetName string, vmInstanceIDs compute.VirtualMachineScaleSetVMInstanceRequiredIDs) *retry.Error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "DeleteInstances", ctx, resourceGroupName, vmScaleSetName, vmInstanceIDs)
ret0, _ := ret[0].(*retry.Error)
return ret0
}
// DeleteInstances indicates an expected call of DeleteInstances
func (mr *MockInterfaceMockRecorder) DeleteInstances(ctx, resourceGroupName, vmScaleSetName, vmInstanceIDs interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteInstances", reflect.TypeOf((*MockInterface)(nil).DeleteInstances), ctx, resourceGroupName, vmScaleSetName, vmInstanceIDs)
}