Skip to content

Commit

Permalink
CB-22348 vertical scale must run only on the targeted group
Browse files Browse the repository at this point in the history
  • Loading branch information
doktoric committed Jun 30, 2023
1 parent 286eb71 commit f89afc2
Show file tree
Hide file tree
Showing 28 changed files with 159 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.List;
import java.util.Map;
import java.util.Optional;

import com.sequenceiq.cloudbreak.cloud.context.AuthenticatedContext;
import com.sequenceiq.cloudbreak.cloud.exception.QuotaExceededException;
Expand Down Expand Up @@ -238,7 +239,8 @@ default CloudDatabaseServerSslCertificate getDatabaseServerActiveSslRootCertific
* @return the status of updated resources
* @throws Exception in case of any error
*/
List<CloudResourceStatus> update(AuthenticatedContext authenticatedContext, CloudStack stack, List<CloudResource> resources, UpdateType type)
List<CloudResourceStatus> update(AuthenticatedContext authenticatedContext, CloudStack stack, List<CloudResource> resources,
UpdateType type, Optional<String> group)
throws Exception;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
Expand Down Expand Up @@ -120,7 +121,8 @@ public List<CloudResourceStatus> upscale(AuthenticatedContext authenticatedConte
}

@Override
public List<CloudResourceStatus> update(AuthenticatedContext authenticatedContext, CloudStack stack, List<CloudResource> resources, UpdateType type) {
public List<CloudResourceStatus> update(AuthenticatedContext authenticatedContext, CloudStack stack,
List<CloudResource> resources, UpdateType type, Optional<String> group) {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import javax.inject.Inject;

Expand Down Expand Up @@ -186,8 +187,9 @@ public CloudDatabaseServerSslCertificate getDatabaseServerActiveSslRootCertifica
}

@Override
public List<CloudResourceStatus> update(AuthenticatedContext authenticatedContext, CloudStack stack, List<CloudResource> resources, UpdateType type) {
return awsUpdateService.update(authenticatedContext, stack, resources, type);
public List<CloudResourceStatus> update(AuthenticatedContext authenticatedContext, CloudStack stack, List<CloudResource> resources,
UpdateType type, Optional<String> group) {
return awsUpdateService.update(authenticatedContext, stack, resources, type, group);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.inject.Inject;
Expand Down Expand Up @@ -49,7 +50,8 @@ public class AwsUpdateService {
@Inject
private AwsLaunchConfigurationUpdateService launchConfigurationUpdateService;

public List<CloudResourceStatus> update(AuthenticatedContext authenticatedContext, CloudStack stack, List<CloudResource> resources, UpdateType type) {
public List<CloudResourceStatus> update(AuthenticatedContext authenticatedContext, CloudStack stack, List<CloudResource> resources,
UpdateType type, Optional<String> targetGroupName) {
ArrayList<CloudResourceStatus> cloudResourceStatuses = new ArrayList<>();
LOGGER.info("The update method which will be followed is {}.", type);
if (!resources.isEmpty()) {
Expand All @@ -67,28 +69,31 @@ public List<CloudResourceStatus> update(AuthenticatedContext authenticatedContex
cloudResourceStatuses.add(new CloudResourceStatus(cloudResource, ResourceStatus.UPDATED)));
}
} else if (type.equals(UpdateType.VERTICAL_SCALE)) {
updateWithVerticalScaling(authenticatedContext, stack, resources);
updateWithVerticalScaling(authenticatedContext, stack, resources, targetGroupName);
}
}
return cloudResourceStatuses;
}

private void updateWithVerticalScaling(AuthenticatedContext authenticatedContext, CloudStack stack, List<CloudResource> resources) {
private void updateWithVerticalScaling(AuthenticatedContext authenticatedContext, CloudStack stack,
List<CloudResource> resources, Optional<String> groupName) {
String cfTemplate = stack.getTemplate();
CloudResource cfResource = getCloudFormationStack(resources);
for (Group group : stack.getGroups()) {
Map<LaunchTemplateField, String> updatableFields = Map.of(
LaunchTemplateField.INSTANCE_TYPE,
group.getReferenceInstanceConfiguration().getTemplate().getFlavor(),
LaunchTemplateField.ROOT_DISK,
String.valueOf(group.getRootVolumeSize())
);
if (cfTemplate.contains(LAUNCH_TEMPLATE)) {
LOGGER.info("Update fields on launchtemplate {} on group {} on cf {}", updatableFields, group.getName(), cfResource.getName());
awsLaunchTemplateUpdateService.updateLaunchTemplate(updatableFields, authenticatedContext, cfResource.getName(), group, stack);
} else {
LOGGER.info("Update fields on launchconfiguration {} on group {} on cf {}", updatableFields, group.getName(), cfResource.getName());
launchConfigurationUpdateService.updateLaunchConfigurations(authenticatedContext, stack, cfResource, updatableFields, group);
if (!groupName.isEmpty() && group.getName().equalsIgnoreCase(groupName.get())) {
Map<LaunchTemplateField, String> updatableFields = Map.of(
LaunchTemplateField.INSTANCE_TYPE,
group.getReferenceInstanceConfiguration().getTemplate().getFlavor(),
LaunchTemplateField.ROOT_DISK,
String.valueOf(group.getRootVolumeSize())
);
if (cfTemplate.contains(LAUNCH_TEMPLATE)) {
LOGGER.info("Update fields on launchtemplate {} on group {} on cf {}", updatableFields, group.getName(), cfResource.getName());
awsLaunchTemplateUpdateService.updateLaunchTemplate(updatableFields, authenticatedContext, cfResource.getName(), group, stack);
} else {
LOGGER.info("Update fields on launchconfiguration {} on group {} on cf {}", updatableFields, group.getName(), cfResource.getName());
launchConfigurationUpdateService.updateLaunchConfigurations(authenticatedContext, stack, cfResource, updatableFields, group);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
Expand Down Expand Up @@ -64,7 +65,8 @@ void updateCloudFormationTemplateResourceWithImageParameter() {
.withParameters(Collections.singletonMap(CloudResource.IMAGE, "dummy"))
.build();

List<CloudResourceStatus> statuses = underTest.update(ac, stack, Collections.singletonList(cloudResource), UpdateType.IMAGE_UPDATE);
List<CloudResourceStatus> statuses = underTest.update(ac, stack, Collections.singletonList(cloudResource),
UpdateType.IMAGE_UPDATE, Optional.empty());

verify(awsImageUpdateService, times(1)).updateImage(ac, stack, cloudResource);
assertEquals(1, statuses.size());
Expand All @@ -83,7 +85,8 @@ void updateCloudFormationTemplateResourceWithoutImageParameter() {
.withType(ResourceType.AWS_LAUNCHCONFIGURATION)
.build();

List<CloudResourceStatus> statuses = underTest.update(ac, stack, List.of(cloudResource, launch), UpdateType.IMAGE_UPDATE);
List<CloudResourceStatus> statuses = underTest.update(ac, stack, List.of(cloudResource, launch),
UpdateType.IMAGE_UPDATE, Optional.empty());

verify(awsImageUpdateService, times(0)).updateImage(ac, stack, cloudResource);
assertEquals(0, statuses.size());
Expand All @@ -102,7 +105,8 @@ void updateRandomResource() {
.withParameters(Collections.singletonMap(CloudResource.IMAGE, "dummy"))
.build();

List<CloudResourceStatus> statuses = underTest.update(ac, stack, List.of(cloudResource, cf), UpdateType.IMAGE_UPDATE);
List<CloudResourceStatus> statuses = underTest.update(ac, stack, List.of(cloudResource, cf),
UpdateType.IMAGE_UPDATE, Optional.empty());

verify(awsImageUpdateService, times(0)).updateImage(ac, stack, cloudResource);
assertEquals(1, statuses.size());
Expand Down Expand Up @@ -157,7 +161,7 @@ void verticalScaleLaunchTemplate() {
when(stack.getTemplate()).thenReturn("AWS::EC2::LaunchTemplate");


underTest.update(ac, stack, Collections.singletonList(cloudResource), UpdateType.VERTICAL_SCALE);
underTest.update(ac, stack, Collections.singletonList(cloudResource), UpdateType.VERTICAL_SCALE, Optional.of("gwGroup"));

Map<LaunchTemplateField, String> updatableFields = Map.of(
LaunchTemplateField.INSTANCE_TYPE,
Expand All @@ -167,6 +171,30 @@ void verticalScaleLaunchTemplate() {
verify(awsLaunchTemplateUpdateService, times(1)).updateLaunchTemplate(eq(updatableFields), any(), eq("cf"), eq(gatewayGroup), eq(stack));
}

@Test
void verticalScaleLaunchTemplateWhenGroupNotPresentedShouldNotCallModificationService() {
CloudResource cloudResource = CloudResource.builder()
.withName("cf")
.withType(ResourceType.CLOUDFORMATION_STACK)
.withParameters(Collections.singletonMap(CloudResource.IMAGE, "dummy"))
.build();
Group gatewayGroup = mock(Group.class);
when(gatewayGroup.getName()).thenReturn("gwGroup");
when(stack.getGroups()).thenReturn(List.of(gatewayGroup));
when(stack.getTemplate()).thenReturn("AWS::EC2::LaunchTemplate");


underTest.update(ac, stack, Collections.singletonList(cloudResource), UpdateType.VERTICAL_SCALE, Optional.of("gwGroup1"));

Map<LaunchTemplateField, String> updatableFields = Map.of(
LaunchTemplateField.INSTANCE_TYPE,
"m42.xxxl",
LaunchTemplateField.ROOT_DISK,
"100");
verify(awsLaunchTemplateUpdateService, times(0)).updateLaunchTemplate(eq(updatableFields), any(), eq("cf"), eq(gatewayGroup), eq(stack));
verify(launchConfigurationUpdateService, times(0)).updateLaunchConfigurations(any(), any(), any(), any());
}

@Test
void verticalScaleLaunchConfig() {
CloudResource cloudResource = CloudResource.builder()
Expand All @@ -186,7 +214,7 @@ void verticalScaleLaunchConfig() {
when(stack.getTemplate()).thenReturn("AWS::EC2::LaunchConfiguration");


underTest.update(ac, stack, Collections.singletonList(cloudResource), UpdateType.VERTICAL_SCALE);
underTest.update(ac, stack, Collections.singletonList(cloudResource), UpdateType.VERTICAL_SCALE, Optional.of("gwGroup"));

Map<LaunchTemplateField, String> updatableFields = Map.of(
LaunchTemplateField.INSTANCE_TYPE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ private void checkIfEveryVolumesAttachedSuccessfullyEvenIfSomethingFailed(CloudR

@Override
public CloudResource update(AwsContext context, CloudResource cloudResource, CloudInstance instance,
AuthenticatedContext auth, CloudStack cloudStack) throws Exception {
AuthenticatedContext auth, CloudStack cloudStack, Optional<String> targetGroupName) throws Exception {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public List<CloudResource> build(AwsContext context, CloudInstance instance, lon

@Override
public CloudResource update(AwsContext context, CloudResource cloudResource, CloudInstance instance,
AuthenticatedContext auth, CloudStack cloudStack) throws Exception {
AuthenticatedContext auth, CloudStack cloudStack, Optional<String> targetGroupName) throws Exception {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ public List<CloudResource> build(AwsContext context, CloudInstance instance, lon

@Override
public CloudResource update(AwsContext context, CloudResource cloudResource, CloudInstance instance,
AuthenticatedContext auth, CloudStack cloudStack) throws Exception {
AuthenticatedContext auth, CloudStack cloudStack, Optional<String> targetGroupName) throws Exception {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.sequenceiq.cloudbreak.cloud.aws.resource.instance;

import java.util.List;
import java.util.Optional;

import com.sequenceiq.cloudbreak.cloud.aws.common.context.AwsContext;
import com.sequenceiq.cloudbreak.cloud.aws.resource.AbstractAwsNativeResourceBuilder;
Expand Down Expand Up @@ -30,7 +31,7 @@ public CloudVmInstanceStatus stop(AwsContext context, AuthenticatedContext auth,

@Override
public CloudResource update(AwsContext context, CloudResource cloudResource, CloudInstance instance,
AuthenticatedContext auth, CloudStack cloudStack) throws Exception {
AuthenticatedContext auth, CloudStack cloudStack, Optional<String> targetGroupName) throws Exception {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ public List<CloudResource> build(AwsContext context, CloudInstance cloudInstance

@Override
public CloudResource update(AwsContext context, CloudResource cloudResource, CloudInstance instance,
AuthenticatedContext auth, CloudStack cloudStack) throws Exception {
AuthenticatedContext auth, CloudStack cloudStack, Optional<String> targetGroup) throws Exception {
AmazonEc2Client amazonEc2Client = context.getAmazonEc2Client();
Optional<Instance> existedOpt = resourceById(amazonEc2Client, instance.getInstanceId());
Instance awsInstance;
Expand All @@ -165,7 +165,11 @@ public CloudResource update(AwsContext context, CloudResource cloudResource, Clo
LOGGER.info("Instance exists with name: {} ({}), check the state: {}", awsInstance.instanceId(), instance.getInstanceId(),
awsInstance.state().name());
String requestedInstanceType = instance.getTemplate().getFlavor();
if (!awsInstance.instanceType().toString().equals(requestedInstanceType)) {
if (isThisGroupApplicable(instance, targetGroup, awsInstance, requestedInstanceType)) {
LOGGER.info("Modify group {}, from instance type {}, to instance type {}.",
targetGroup.get(),
awsInstance.instanceType().name(),
instance.getTemplate().getFlavor());
ModifyInstanceAttributeRequest modifyInstanceAttributeRequest = ModifyInstanceAttributeRequest.builder()
.instanceId(awsInstance.instanceId())
.instanceType(AttributeValue.builder().value(instance.getTemplate().getFlavor()).build())
Expand All @@ -179,6 +183,11 @@ public CloudResource update(AwsContext context, CloudResource cloudResource, Clo
return null;
}

private boolean isThisGroupApplicable(CloudInstance instance, Optional<String> targetGroup, Instance awsInstance, String requestedInstanceType) {
return !targetGroup.isEmpty() && targetGroup.equals(instance.getTemplate().getGroupName())
&& !awsInstance.instanceType().toString().equals(requestedInstanceType);
}

Collection<BlockDeviceMapping> blocks(Group group, CloudStack cloudStack, AuthenticatedContext ac) {
AwsInstanceView awsInstanceView = new AwsInstanceView(group.getReferenceInstanceTemplate());
List<BlockDeviceMapping> blocks = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import javax.inject.Inject;

Expand Down Expand Up @@ -331,14 +332,14 @@ public List<CloudResourceStatus> terminateDatabaseServer(AuthenticatedContext au
}

@Override
public List<CloudResourceStatus> update(AuthenticatedContext authenticatedContext, CloudStack stack, List<CloudResource> resources, UpdateType type)
throws QuotaExceededException {
public List<CloudResourceStatus> update(AuthenticatedContext authenticatedContext, CloudStack stack, List<CloudResource> resources,
UpdateType type, Optional<String> group) throws QuotaExceededException {
LOGGER.info("The update method which will be followed is {}.", type);
if (type.equals(UpdateType.VERTICAL_SCALE)) {
AzureClient client = authenticatedContext.getParameter(AzureClient.class);
AzureStackView azureStackView = azureStackViewProvider
.getAzureStack(new AzureCredentialView(authenticatedContext.getCloudCredential()), stack, client, authenticatedContext);
return azureVerticalScaleService.verticalScale(authenticatedContext, stack, resources, azureStackView, client);
return azureVerticalScaleService.verticalScale(authenticatedContext, stack, resources, azureStackView, client, group);
}
return List.of();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.sequenceiq.cloudbreak.cloud.azure.resource;

import java.util.List;
import java.util.Optional;

import com.sequenceiq.cloudbreak.cloud.azure.context.AzureContext;
import com.sequenceiq.cloudbreak.cloud.context.AuthenticatedContext;
Expand Down Expand Up @@ -34,7 +35,7 @@ public CloudVmInstanceStatus start(AzureContext context, AuthenticatedContext au

@Override
public CloudResource update(AzureContext context, CloudResource cloudResource, CloudInstance instance,
AuthenticatedContext auth, CloudStack cloudStack) throws Exception {
AuthenticatedContext auth, CloudStack cloudStack, Optional<String> targetGroupName) throws Exception {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.inject.Inject;
Expand Down Expand Up @@ -40,7 +41,7 @@ public class AzureVerticalScaleService {
private AzureVirtualMachineService azureVirtualMachineService;

public List<CloudResourceStatus> verticalScale(AuthenticatedContext ac, CloudStack stack, List<CloudResource> resources, AzureStackView azureStackView,
AzureClient client) throws QuotaExceededException {
AzureClient client, Optional<String> group) throws QuotaExceededException {
CloudContext cloudContext = ac.getCloudContext();
String stackName = azureUtils.getStackName(cloudContext);
try {
Expand All @@ -56,8 +57,10 @@ public List<CloudResourceStatus> verticalScale(AuthenticatedContext ac, CloudSta
.stream()
.filter(value -> value.name().equals(cloudInstance.getInstanceId()))
.filter(value -> !value.size().toString().equalsIgnoreCase(cloudInstance.getTemplate().getFlavor()))
.filter(value -> cloudInstance.getTemplate().getGroupName().equalsIgnoreCase(group.get()))
.forEach(value -> {
LOGGER.info("Vertical scaling vm {} with flavor {}.", value.name(), cloudInstance.getTemplate().getFlavor());
LOGGER.info("Vertical scaling group {} vm {} with flavor {}.",
group.get(), value.name(), cloudInstance.getTemplate().getFlavor());
client.modifyInstanceType(resourceGroupName, value.name(), cloudInstance.getTemplate().getFlavor());
});
}
Expand Down
Loading

0 comments on commit f89afc2

Please sign in to comment.