Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions pkg/frontend/admin_openshiftcluster_vmresize.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,22 @@ func (f *frontend) _postAdminOpenShiftClusterVMResize(log *logrus.Entry, ctx con
resourceType := chi.URLParam(r, "resourceType")
resourceGroupName := chi.URLParam(r, "resourceGroupName")
vmSize := r.URL.Query().Get("vmSize")
useCapacityReservation := strings.EqualFold(r.URL.Query().Get("useCapacityReservation"), "true")

action, _, err := f.prepareAdminActions(log, ctx, vmName, strings.TrimPrefix(r.URL.Path, "/admin"), resourceType, resourceName, resourceGroupName)
err := validateAdminMasterVMSize(vmSize)
if err != nil {
return err
}

err = validateAdminMasterVMSize(vmSize)
if useCapacityReservation {
action, _, err := f.prepareAdminActionsForCluster(log, ctx, strings.TrimPrefix(r.URL.Path, "/admin"), resourceType, resourceName, resourceGroupName)
if err != nil {
return err
}
return action.VMResizeWithCapacityReservation(ctx, vmSize)
}

action, _, err := f.prepareAdminActions(log, ctx, vmName, strings.TrimPrefix(r.URL.Path, "/admin"), resourceType, resourceName, resourceGroupName)
if err != nil {
return err
}
Expand Down
41 changes: 29 additions & 12 deletions pkg/frontend/admin_openshiftcluster_vmresize_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,16 @@ func TestAdminVMResize(t *testing.T) {
}

type test struct {
name string
resourceID string
vmName string
vmSize string
fixture func(f *testdatabase.Fixture)
azureActionsMocks func(*test, *mock_adminactions.MockAzureActions)
wantStatusCode int
wantResponse []byte
wantError string
name string
resourceID string
vmName string
vmSize string
useCapacityReservation bool
fixture func(f *testdatabase.Fixture)
azureActionsMocks func(*test, *mock_adminactions.MockAzureActions)
wantStatusCode int
wantResponse []byte
wantError string
}

for _, tt := range []*test{
Expand All @@ -80,6 +81,20 @@ func TestAdminVMResize(t *testing.T) {
},
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add focused unit tests for VMResizeWithCapacityReservation itself (in pkg/frontend/adminactions) in addition to this routing-level test? The high-risk paths seem to be: mixed-SKU zone retries, reservation-create failures, and cleanup ordering when association/resize/start fail.

Refs:

wantStatusCode: http.StatusOK,
},
{
name: "capacity reservation path",
vmSize: "Standard_D8s_v3",
useCapacityReservation: true,
resourceID: testdatabase.GetResourcePath(mockSubID, "resourceName"),
fixture: func(f *testdatabase.Fixture) {
addClusterDoc(f)
addSubscriptionDoc(f)
},
azureActionsMocks: func(tt *test, a *mock_adminactions.MockAzureActions) {
a.EXPECT().VMResizeWithCapacityReservation(gomock.Any(), tt.vmSize).Return(nil)
},
wantStatusCode: http.StatusOK,
},
{
name: "cluster not found",
vmName: "aro-fake-node-master-0",
Expand Down Expand Up @@ -156,9 +171,11 @@ func TestAdminVMResize(t *testing.T) {

go f.Run(ctx, nil, nil)

resp, b, err := ti.request(http.MethodPost,
fmt.Sprintf("https://server/admin%s/resize?vmName=%s&vmSize=%s", tt.resourceID, tt.vmName, tt.vmSize),
nil, nil)
url := fmt.Sprintf("https://server/admin%s/resize?vmName=%s&vmSize=%s", tt.resourceID, tt.vmName, tt.vmSize)
if tt.useCapacityReservation {
url += "&useCapacityReservation=true"
}
resp, b, err := ti.request(http.MethodPost, url, nil, nil)
if err != nil {
t.Fatal(err)
}
Expand Down
5 changes: 5 additions & 0 deletions pkg/frontend/admin_vm_actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ func (f *frontend) prepareAdminActions(log *logrus.Entry, ctx context.Context, v
if err != nil {
return nil, nil, err
}
return f.prepareAdminActionsForCluster(log, ctx, resourceID, resourceType, resourceName, resourceGroupName)
}

// prepareAdminActionsForCluster is like prepareAdminActions but does not require or validate a VM name.
// Use this for operations that act on the whole cluster rather than a specific VM.
func (f *frontend) prepareAdminActionsForCluster(log *logrus.Entry, ctx context.Context, resourceID string, resourceType, resourceName, resourceGroupName string) (azureActions adminactions.AzureActions, doc *api.OpenShiftClusterDocument, err error) {
dbOpenShiftClusters, err := f.dbGroup.OpenShiftClusters()
if err != nil {
return nil, nil, err
Expand Down
62 changes: 42 additions & 20 deletions pkg/frontend/adminactions/azureactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type AzureActions interface {
VMStopAndWait(ctx context.Context, vmName string, deallocateVM bool) error
VMSizeList(ctx context.Context) ([]*sdkcompute.ResourceSKU, error)
VMResize(ctx context.Context, vmName string, vmSize string) error
VMResizeWithCapacityReservation(ctx context.Context, targetVMSize string) error
ResourceGroupHasVM(ctx context.Context, vmName string) (bool, error)
VMSerialConsole(ctx context.Context, log *logrus.Entry, vmName string, target io.Writer) error
ResourceDeleteAndWait(ctx context.Context, resourceID string) error
Expand All @@ -47,16 +48,19 @@ type azureActions struct {
env env.Interface
oc *api.OpenShiftCluster

networkInterfaces armnetwork.InterfacesClient
diskEncryptionSets compute.DiskEncryptionSetsClient
loadBalancers armnetwork.LoadBalancersClient
resources features.ResourcesClient
resourceSkus armcompute.ResourceSKUsClient
routeTables armnetwork.RouteTablesClient
securityGroups armnetwork.SecurityGroupsClient
storageAccounts storage.AccountsClient
virtualMachines compute.VirtualMachinesClient
virtualNetworks armnetwork.VirtualNetworksClient
networkInterfaces armnetwork.InterfacesClient
diskEncryptionSets compute.DiskEncryptionSetsClient
loadBalancers armnetwork.LoadBalancersClient
resources features.ResourcesClient
resourceSkus armcompute.ResourceSKUsClient
routeTables armnetwork.RouteTablesClient
securityGroups armnetwork.SecurityGroupsClient
storageAccounts storage.AccountsClient
virtualMachines compute.VirtualMachinesClient
virtualNetworks armnetwork.VirtualNetworksClient
armVirtualMachines armcompute.VirtualMachinesClient
armCapacityReservationGroups armcompute.CapacityReservationGroupsClient
armCapacityReservations armcompute.CapacityReservationsClient
}

// NewAzureActions returns an azureActions
Expand Down Expand Up @@ -106,21 +110,39 @@ func NewAzureActions(log *logrus.Entry, env env.Interface, oc *api.OpenShiftClus
return nil, err
}

armVMsClient, err := armcompute.NewVirtualMachinesClient(subscriptionDoc.ID, credential, options)
if err != nil {
return nil, err
}

armCRGClient, err := armcompute.NewCapacityReservationGroupsClient(subscriptionDoc.ID, credential, options)
if err != nil {
return nil, err
}

armCRClient, err := armcompute.NewCapacityReservationsClient(subscriptionDoc.ID, credential, options)
if err != nil {
return nil, err
}

return &azureActions{
log: log,
env: env,
oc: oc,

networkInterfaces: networkInterfaces,
diskEncryptionSets: compute.NewDiskEncryptionSetsClientWithAROEnvironment(env.Environment(), subscriptionDoc.ID, fpAuth),
loadBalancers: loadBalancers,
resources: features.NewResourcesClient(env.Environment(), subscriptionDoc.ID, fpAuth),
resourceSkus: armResourceSKUsClient,
routeTables: routeTables,
securityGroups: securityGroups,
storageAccounts: storage.NewAccountsClient(env.Environment(), subscriptionDoc.ID, fpAuth),
virtualMachines: compute.NewVirtualMachinesClient(env.Environment(), subscriptionDoc.ID, fpAuth),
virtualNetworks: virtualNetworks,
networkInterfaces: networkInterfaces,
diskEncryptionSets: compute.NewDiskEncryptionSetsClientWithAROEnvironment(env.Environment(), subscriptionDoc.ID, fpAuth),
loadBalancers: loadBalancers,
resources: features.NewResourcesClient(env.Environment(), subscriptionDoc.ID, fpAuth),
resourceSkus: armResourceSKUsClient,
routeTables: routeTables,
securityGroups: securityGroups,
storageAccounts: storage.NewAccountsClient(env.Environment(), subscriptionDoc.ID, fpAuth),
virtualMachines: compute.NewVirtualMachinesClient(env.Environment(), subscriptionDoc.ID, fpAuth),
virtualNetworks: virtualNetworks,
armVirtualMachines: armVMsClient,
armCapacityReservationGroups: armCRGClient,
armCapacityReservations: armCRClient,
}, nil
}

Expand Down
Loading