Skip to content

Commit

Permalink
Resize node api uses yb.internal.allow_unsupported_instances flag
Browse files Browse the repository at this point in the history
Summary: Resize node api uses yb.internal.allow_unsupported_instances flag

Test Plan:
Create universe using instance type manually added to provider, set the flag, and call
the resize node api. Should not error. Unset the flag and call the api again. Should error.

Reviewers: sanketh, muthu, cdavid

Reviewed By: muthu, cdavid

Subscribers: jenkins-bot, yugaware

Differential Revision: https://phabricator.dev.yugabyte.com/D18231
  • Loading branch information
vmallepalli committed Jul 11, 2022
1 parent 1418288 commit 1634fb2
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.google.common.collect.ImmutableList;
import com.yugabyte.yw.commissioner.Common.CloudType;
import com.yugabyte.yw.commissioner.tasks.UniverseDefinitionTaskBase.ServerType;
import com.yugabyte.yw.common.config.RuntimeConfigFactory;
import com.yugabyte.yw.common.utils.Pair;
import com.yugabyte.yw.forms.ResizeNodeParams;
import com.yugabyte.yw.forms.UniverseConfigureTaskParams;
Expand Down Expand Up @@ -60,6 +61,7 @@
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import play.api.Play;

public class PlacementInfoUtil {
public static final Logger LOG = LoggerFactory.getLogger(PlacementInfoUtil.class);
Expand Down Expand Up @@ -514,9 +516,17 @@ private static void updateUniverseDefinition(
+ " cluster in universe "
+ universe.universeUUID);
}

// Checking resize restrictions (provider, instance, volume size, etc).
RuntimeConfigFactory runtimeConfigFactory =
Play.current().injector().instanceOf(RuntimeConfigFactory.class);
boolean allowUnsupportedInstances =
runtimeConfigFactory
.forUniverse(universe)
.getBoolean("yb.internal.allow_unsupported_instances");
String checkResizePossible =
ResizeNodeParams.checkResizeIsPossible(oldCluster.userIntent, cluster.userIntent);
ResizeNodeParams.checkResizeIsPossible(
oldCluster.userIntent, cluster.userIntent, allowUnsupportedInstances);

// Besides restrictions, resize is only available if no nodes are added/removed.
taskParams.nodesResizeAvailable =
Expand Down
42 changes: 21 additions & 21 deletions managed/src/main/java/com/yugabyte/yw/forms/ResizeNodeParams.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.typesafe.config.Config;
import com.yugabyte.yw.commissioner.Common;
import com.yugabyte.yw.common.ConfigHelper;
import com.yugabyte.yw.common.config.RuntimeConfigFactory;
import com.yugabyte.yw.models.InstanceType;
import com.yugabyte.yw.models.Provider;
import com.yugabyte.yw.models.Universe;
Expand All @@ -16,6 +17,8 @@
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -42,13 +45,20 @@ public void verifyParams(Universe universe) {
"Only ROLLING_UPGRADE option is supported for resizing node (changing VM type).");
}

RuntimeConfigFactory runtimeConfigFactory =
Play.current().injector().instanceOf(RuntimeConfigFactory.class);
boolean allowUnsupportedInstances =
runtimeConfigFactory
.forUniverse(universe)
.getBoolean("yb.internal.allow_unsupported_instances");

for (Cluster cluster : clusters) {
UserIntent newUserIntent = cluster.userIntent;
UserIntent currentUserIntent =
universe.getUniverseDetails().getClusterByUuid(cluster.uuid).userIntent;

String errorStr =
checkResizeIsPossible(currentUserIntent, newUserIntent, isSkipInstanceChecking());
checkResizeIsPossible(currentUserIntent, newUserIntent, allowUnsupportedInstances);
if (errorStr != null) {
throw new IllegalArgumentException(errorStr);
}
Expand All @@ -58,17 +68,13 @@ public void verifyParams(Universe universe) {
/**
* Checks if smart resize is available
*
* @param currentUserIntent
* @param newUserIntent
* @param currentUserIntent current user intent
* @param newUserIntent desired user intent
* @param allowUnsupportedInstances boolean to skip instance type checking
* @return null if available, otherwise returns error message
*/
public static String checkResizeIsPossible(
UserIntent currentUserIntent, UserIntent newUserIntent) {
return checkResizeIsPossible(currentUserIntent, newUserIntent, false);
}

private static String checkResizeIsPossible(
UserIntent currentUserIntent, UserIntent newUserIntent, boolean skipInstanceChecking) {
UserIntent currentUserIntent, UserIntent newUserIntent, boolean allowUnsupportedInstances) {
if (currentUserIntent == null || newUserIntent == null) {
return "Should have both intents, but got: " + currentUserIntent + ", " + newUserIntent;
}
Expand Down Expand Up @@ -107,35 +113,29 @@ private static String checkResizeIsPossible(
return "ResizeNode operation is not supported for instances with ephemeral drives";
}
// Checking new instance is valid.
if (!newInstanceTypeCode.equals(currentUserIntent.instanceType) && !skipInstanceChecking) {
if (!newInstanceTypeCode.equals(currentUserIntent.instanceType)) {
String provider = currentUserIntent.provider;
List<InstanceType> instanceTypes =
InstanceType.findByProvider(
Provider.getOrBadRequest(UUID.fromString(provider)),
Play.current().injector().instanceOf(Config.class),
Play.current().injector().instanceOf(ConfigHelper.class));
log.info(instanceTypes.toString());
Play.current().injector().instanceOf(ConfigHelper.class),
allowUnsupportedInstances);
InstanceType newInstanceType =
instanceTypes
.stream()
.filter(type -> type.getInstanceTypeCode().equals(newInstanceTypeCode))
.findFirst()
.orElse(null);
if (newInstanceType == null) {
return "Provider "
+ currentUserIntent.providerType
+ " does not have the intended instance type "
+ newInstanceTypeCode;
return String.format(
"Provider %s of type %s does not contain the intended instance type '%s'",
currentUserIntent.provider, currentUserIntent.providerType, newInstanceTypeCode);
}
}

return null;
}

@VisibleForTesting
protected boolean isSkipInstanceChecking() {
return false;
}

public static class Converter extends BaseConverter<ResizeNodeParams> {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import com.yugabyte.yw.forms.ResizeNodeParams;
import com.yugabyte.yw.forms.UniverseDefinitionTaskParams;
import com.yugabyte.yw.forms.UpgradeTaskParams;
import com.yugabyte.yw.models.InstanceType;
import com.yugabyte.yw.models.RuntimeConfigEntry;
import com.yugabyte.yw.models.TaskInfo;
import com.yugabyte.yw.models.Universe;
import com.yugabyte.yw.models.helpers.DeviceInfo;
Expand Down Expand Up @@ -53,6 +55,7 @@ public class ResizeNodeTest extends UpgradeTaskTest {

private static final String DEFAULT_INSTANCE_TYPE = "c3.medium";
private static final String NEW_INSTANCE_TYPE = "c4.medium";
private static final String NEW_READ_ONLY_INSTANCE_TYPE = "c3.small";

private static final int DEFAULT_VOLUME_SIZE = 100;
private static final int NEW_VOLUME_SIZE = 200;
Expand Down Expand Up @@ -105,7 +108,14 @@ public void setUp() {
userIntent.deviceInfo.volumeSize = DEFAULT_VOLUME_SIZE;
userIntent.instanceType = DEFAULT_INSTANCE_TYPE;
});

InstanceType.upsert(
defaultProvider.uuid, NEW_INSTANCE_TYPE, 2.0, 8.0, new InstanceType.InstanceTypeDetails());
InstanceType.upsert(
defaultProvider.uuid,
NEW_READ_ONLY_INSTANCE_TYPE,
2.0,
8.0,
new InstanceType.InstanceTypeDetails());
try {
when(mockYBClient.getClientWithConfig(any())).thenReturn(mockClient);
ListMastersResponse listMastersResponse = mock(ListMastersResponse.class);
Expand Down Expand Up @@ -283,6 +293,7 @@ public void testChangingInstanceWithReadonlyReplicaChanging() {
userIntent.deviceInfo.volumeSize = DEFAULT_VOLUME_SIZE;
userIntent.instanceType = DEFAULT_INSTANCE_TYPE;
userIntent.providerType = curIntent.providerType;
userIntent.provider = curIntent.provider;
PlacementInfo pi = new PlacementInfo();
PlacementInfoUtil.addPlacementZone(az1.uuid, pi, 1, 1, false);
PlacementInfoUtil.addPlacementZone(az2.uuid, pi, 1, 1, false);
Expand All @@ -306,7 +317,7 @@ public void testChangingInstanceWithReadonlyReplicaChanging() {
taskParams.getPrimaryCluster().userIntent.deviceInfo.volumeSize = NEW_VOLUME_SIZE;
taskParams.getPrimaryCluster().userIntent.instanceType = NEW_INSTANCE_TYPE;
taskParams.getReadOnlyClusters().get(0).userIntent.deviceInfo.volumeSize = 250;
taskParams.getReadOnlyClusters().get(0).userIntent.instanceType = "c3.small";
taskParams.getReadOnlyClusters().get(0).userIntent.instanceType = NEW_READ_ONLY_INSTANCE_TYPE;
taskParams.getReadOnlyClusters().get(0).userIntent.providerType = Common.CloudType.aws;
TaskInfo taskInfo = submitTask(taskParams);
assertEquals(Success, taskInfo.getTaskState());
Expand All @@ -328,6 +339,7 @@ public void testChangingInstanceWithOnlyReadonlyReplicaChanging() {
userIntent.deviceInfo.volumeSize = DEFAULT_VOLUME_SIZE;
userIntent.instanceType = DEFAULT_INSTANCE_TYPE;
userIntent.providerType = curIntent.providerType;
userIntent.provider = curIntent.provider;
PlacementInfo pi = new PlacementInfo();
PlacementInfoUtil.addPlacementZone(az1.uuid, pi, 1, 1, false);
PlacementInfoUtil.addPlacementZone(az2.uuid, pi, 1, 1, false);
Expand Down Expand Up @@ -597,13 +609,8 @@ private TaskInfo submitTask(ResizeNodeParams requestParams) {
}

private ResizeNodeParams createResizeParams() {
ResizeNodeParams taskParams =
new ResizeNodeParams() {
@Override
protected boolean isSkipInstanceChecking() {
return true;
}
};
ResizeNodeParams taskParams = new ResizeNodeParams();
RuntimeConfigEntry.upsertGlobal("yb.internal.allow_unsupported_instances", "true");
taskParams.universeUUID = defaultUniverse.universeUUID;
return taskParams;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package com.yugabyte.yw.controllers.handlers;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.yugabyte.yw.commissioner.Commissioner;
Expand All @@ -25,23 +26,23 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;

@RunWith(JUnitParamsRunner.class)
public class UpgradeUniverseHandlerTest {
private static final String DEFAULT_INSTANCE_TYPE = "type1";
private static final String NEW_INSTANCE_TYPE = "type2";
private UpgradeUniverseHandler handler;
private Commissioner mockCommissioner;

@Before
public void setUp() {
mockCommissioner = Mockito.mock(Commissioner.class);
Commissioner mockCommissioner = mock(Commissioner.class);
when(mockCommissioner.submit(any(TaskType.class), any(ITaskParams.class)))
.thenReturn(UUID.randomUUID());
handler =
new UpgradeUniverseHandler(
mockCommissioner,
Mockito.mock(KubernetesManagerFactory.class),
Mockito.mock(RuntimeConfigFactory.class));
mock(KubernetesManagerFactory.class),
mock(RuntimeConfigFactory.class));
}

private static Object[] tlsToggleCustomTypeNameParams() {
Expand Down Expand Up @@ -89,7 +90,7 @@ public void testMergeResizeNodeParamsWithIntent() {
intent.deviceInfo.volumeSize = 100;
intent.deviceInfo.numVolumes = 2;
intent.replicationFactor = 35;
intent.instanceType = "type1";
intent.instanceType = DEFAULT_INSTANCE_TYPE;
UUID universeCA = UUID.randomUUID();
Universe universe = new Universe();
UniverseDefinitionTaskParams taskParams = new UniverseDefinitionTaskParams();
Expand All @@ -104,21 +105,15 @@ public void testMergeResizeNodeParamsWithIntent() {
universe.getUniverseDetails().rootCA = universeCA;
universe.getUniverseDetails().clientRootCA = universeCA;

ResizeNodeParams resizeNodeParams =
new ResizeNodeParams() {
@Override
protected boolean isSkipInstanceChecking() {
return true;
}
};
ResizeNodeParams resizeNodeParams = new ResizeNodeParams();
resizeNodeParams.upgradeOption = UpgradeTaskParams.UpgradeOption.ROLLING_UPGRADE;
resizeNodeParams.rootCA = UUID.randomUUID();
resizeNodeParams.clientRootCA = UUID.randomUUID();
UniverseDefinitionTaskParams.UserIntent requestIntent =
new UniverseDefinitionTaskParams.UserIntent();
requestIntent.deviceInfo = new DeviceInfo();
requestIntent.deviceInfo.volumeSize = 150;
requestIntent.instanceType = "type2";
requestIntent.instanceType = NEW_INSTANCE_TYPE;
resizeNodeParams.clusters =
Collections.singletonList(
new UniverseDefinitionTaskParams.Cluster(
Expand All @@ -131,7 +126,7 @@ protected boolean isSkipInstanceChecking() {
UniverseDefinitionTaskParams.UserIntent submitIntent =
resizeNodeParams.getPrimaryCluster().userIntent;
Assert.assertEquals(35, submitIntent.replicationFactor);
Assert.assertEquals("type2", submitIntent.instanceType);
Assert.assertEquals(NEW_INSTANCE_TYPE, submitIntent.instanceType);
Assert.assertEquals(150, submitIntent.deviceInfo.volumeSize.intValue());
Assert.assertEquals(2, submitIntent.deviceInfo.numVolumes.intValue());
}
Expand Down

0 comments on commit 1634fb2

Please sign in to comment.