Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Azure: Enrich the unit tests for azure clients and azure zones. #90389

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -24,6 +24,19 @@ import (
"net"
"net/http"
"testing"

"k8s.io/apimachinery/pkg/util/sets"
cloudprovider "k8s.io/cloud-provider"
"k8s.io/legacy-cloud-providers/azure/clients/vmclient/mockvmclient"

"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute"
"github.com/Azure/go-autorest/autorest/to"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
)

const (
testAvailabilitySetNodeProviderID = "azure:///subscriptions/sub/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/vm-0"
)

func TestIsAvailabilityZone(t *testing.T) {
Expand Down Expand Up @@ -91,6 +104,8 @@ func TestGetZone(t *testing.T) {
location string
faultDomain string
expected string
isNilResp bool
expectedErr error
}{
{
name: "GetZone should get real zone if only node's zone is set",
Expand All @@ -117,6 +132,19 @@ func TestGetZone(t *testing.T) {
zone: "1",
expected: "eastus-1",
},
{
name: "GetZone should report an error if there is no `Compute` in the response",
isNilResp: true,
expectedErr: fmt.Errorf("failure of getting compute information from instance metadata"),
},
{
name: "GetZone should report an error if the zone is invalid",
zone: "a",
location: "eastus",
faultDomain: "99",
expected: "",
expectedErr: fmt.Errorf("failed to parse zone ID \"a\": strconv.Atoi: parsing \"a\": invalid syntax"),
},
}

for _, test := range testcases {
Expand All @@ -125,9 +153,13 @@ func TestGetZone(t *testing.T) {
t.Errorf("Test [%s] unexpected error: %v", test.name, err)
}

respString := fmt.Sprintf(`{"compute":{"zone":"%s", "platformFaultDomain":"%s", "location":"%s"}}`, test.zone, test.faultDomain, test.location)
if test.isNilResp {
respString = "{}"
}
mux := http.NewServeMux()
mux.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, fmt.Sprintf(`{"compute":{"zone":"%s", "platformFaultDomain":"%s", "location":"%s"}}`, test.zone, test.faultDomain, test.location))
fmt.Fprint(w, respString)
}))
go func() {
http.Serve(listener, mux)
Expand All @@ -141,13 +173,72 @@ func TestGetZone(t *testing.T) {

zone, err := cloud.GetZone(context.Background())
if err != nil {
t.Errorf("Test [%s] unexpected error: %v", test.name, err)
if test.expectedErr == nil {
t.Errorf("Test [%s] unexpected error: %v", test.name, err)
} else {
assert.Equal(t, test.expectedErr, err)
}
}
if zone.FailureDomain != test.expected {
t.Errorf("Test [%s] unexpected zone: %s, expected %q", test.name, zone.FailureDomain, test.expected)
}
if zone.Region != cloud.Location {
if err == nil && zone.Region != cloud.Location {
t.Errorf("Test [%s] unexpected region: %s, expected: %s", test.name, zone.Region, cloud.Location)
}
}
}

func TestMakeZone(t *testing.T) {
az := &Cloud{}
zone := az.makeZone("EASTUS", 2)
assert.Equal(t, "eastus-2", zone)
}

func TestGetZoneByProviderID(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

az := GetTestCloud(ctrl)

zone, err := az.GetZoneByProviderID(context.Background(), "")
assert.Equal(t, errNodeNotInitialized, err)
assert.Equal(t, cloudprovider.Zone{}, zone)

zone, err = az.GetZoneByProviderID(context.Background(), "invalid/id")
assert.NoError(t, err)
assert.Equal(t, cloudprovider.Zone{}, zone)

mockVMClient := az.VirtualMachinesClient.(*mockvmclient.MockInterface)
mockVMClient.EXPECT().Get(gomock.Any(), az.ResourceGroup, "vm-0", gomock.Any()).Return(compute.VirtualMachine{
Zones: &[]string{"1"},
Location: to.StringPtr("eastus"),
}, nil)
zone, err = az.GetZoneByProviderID(context.Background(), testAvailabilitySetNodeProviderID)
assert.NoError(t, err)
assert.Equal(t, cloudprovider.Zone{
FailureDomain: "eastus-1",
Region: "eastus",
}, zone)
}

func TestAvailabilitySetGetZoneByNodeName(t *testing.T) {
az := &Cloud{
unmanagedNodes: sets.String{"vm-0": sets.Empty{}},
nodeInformerSynced: func() bool {
return true
},
}
zone, err := az.GetZoneByNodeName(context.Background(), "vm-0")
assert.NoError(t, err)
assert.Equal(t, cloudprovider.Zone{}, zone)

az = &Cloud{
unmanagedNodes: sets.String{"vm-0": sets.Empty{}},
nodeInformerSynced: func() bool {
return false
},
}
zone, err = az.GetZoneByNodeName(context.Background(), "vm-0")
assert.Equal(t, fmt.Errorf("node informer is not synced when trying to GetUnmanagedNodes"), err)
assert.Equal(t, cloudprovider.Zone{}, zone)
}
Expand Up @@ -285,7 +285,7 @@ func (c *Client) SendAsync(ctx context.Context, request *http.Request) (*azure.F

future, err := azure.NewFutureFromResponse(asyncResponse)
if err != nil {
klog.V(5).Infof("Received error in %s: resourceID: %s, error: %s", "sendAsync.responed", request.URL.String(), err)
klog.V(5).Infof("Received error in %s: resourceID: %s, error: %s", "sendAsync.respond", request.URL.String(), err)
return nil, asyncResponse, retry.GetError(asyncResponse, err)
}

Expand Down Expand Up @@ -337,7 +337,7 @@ func (c *Client) PutResource(ctx context.Context, resourceID string, parameters
}

// PutResources puts a list of resources from resources map[resourceID]parameters.
// Those resources sync requests are sequential while async requests are concurent. It 's especially
// Those resources sync requests are sequential while async requests are concurrent. It's especially
// useful when the ARM API doesn't support concurrent requests.
func (c *Client) PutResources(ctx context.Context, resources map[string]interface{}) map[string]*PutResourcesResponse {
if len(resources) == 0 {
Expand Down