mirror of
https://github.com/google/nomulus.git
synced 2025-08-03 08:22:13 +02:00
Remove AppEngineServiceUtils (#2003)
The only method that is called from this class is setNumInstances. However we don't current use `nomulus set_num_instances` anywhere. If we need to change the number of instances, it is either done by updating appengine-web.xml, which is deployed by Spinnaker, or doing it manually as a break-glass fix via gcloud or on Pantheon.
This commit is contained in:
parent
23fb69a682
commit
bd0cea0d87
9 changed files with 1 additions and 712 deletions
|
@ -97,7 +97,6 @@ public final class RegistryTool {
|
|||
.put("save_sql_credential", SaveSqlCredentialCommand.class)
|
||||
.put("send_escrow_report_to_icann", SendEscrowReportToIcannCommand.class)
|
||||
.put("set_database_migration_state", SetDatabaseMigrationStateCommand.class)
|
||||
.put("set_num_instances", SetNumInstancesCommand.class)
|
||||
.put("setup_ote", SetupOteCommand.class)
|
||||
.put("uniform_rapid_suspension", UniformRapidSuspensionCommand.class)
|
||||
.put("unlock_domain", UnlockDomainCommand.class)
|
||||
|
|
|
@ -144,8 +144,6 @@ interface RegistryToolComponent {
|
|||
|
||||
void inject(SendEscrowReportToIcannCommand command);
|
||||
|
||||
void inject(SetNumInstancesCommand command);
|
||||
|
||||
void inject(SetupOteCommand command);
|
||||
|
||||
void inject(UniformRapidSuspensionCommand command);
|
||||
|
|
|
@ -1,172 +0,0 @@
|
|||
// Copyright 2018 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.collect.ImmutableSetMultimap.flatteningToImmutableSetMultimap;
|
||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.api.services.appengine.v1.Appengine;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.request.Action.Service;
|
||||
import google.registry.util.AppEngineServiceUtils;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/** A command to set the number of instances for an App Engine service. */
|
||||
@Parameters(
|
||||
separators = " =",
|
||||
commandDescription =
|
||||
"Set the number of instances for a given service and version. "
|
||||
+ "Note that this command only works for manual scaling service.")
|
||||
final class SetNumInstancesCommand implements Command {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private static final ImmutableList<Service> ALL_DEPLOYED_SERVICES =
|
||||
ImmutableList.copyOf(Service.values());
|
||||
|
||||
private static final ImmutableMap<String, Service> SERVICE_ID_TO_SERVICE =
|
||||
Maps.uniqueIndex(ALL_DEPLOYED_SERVICES, Service::getServiceId);
|
||||
|
||||
@Parameter(
|
||||
names = {"-s", "--services"},
|
||||
description =
|
||||
"Comma-delimited list of App Engine services to set. "
|
||||
+ "Allowed values: [DEFAULT, TOOLS, BACKEND, PUBAPI]")
|
||||
private List<Service> services = ImmutableList.of();
|
||||
|
||||
@Parameter(
|
||||
names = {"-v", "--versions"},
|
||||
description =
|
||||
"Comma-delimited list of App Engine versions to set, e.g., canary. "
|
||||
+ "Cannot be set if --non_live_versions is set.")
|
||||
private List<String> versions = ImmutableList.of();
|
||||
|
||||
@Parameter(
|
||||
names = {"-n", "--num_instances"},
|
||||
description =
|
||||
"The new number of instances for the given versions "
|
||||
+ "or for all non-live versions if --non_live_versions is set.",
|
||||
required = true)
|
||||
private Long numInstances;
|
||||
|
||||
@Parameter(
|
||||
names = "--non_live_versions",
|
||||
description = "Whether to set number of instances for all non-live versions.",
|
||||
arity = 1)
|
||||
private Boolean nonLiveVersions = false;
|
||||
|
||||
@Inject AppEngineServiceUtils appEngineServiceUtils;
|
||||
@Inject Appengine appengine;
|
||||
|
||||
@Inject
|
||||
@Config("projectId")
|
||||
String projectId;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (nonLiveVersions) {
|
||||
checkArgument(versions.isEmpty(), "--versions cannot be set if --non_live_versions is set");
|
||||
|
||||
services = services.isEmpty() ? ALL_DEPLOYED_SERVICES : services;
|
||||
ImmutableSetMultimap<Service, String> allLiveVersionsMap = getAllLiveVersionsMap(services);
|
||||
ImmutableSetMultimap<Service, String> manualScalingVersionsMap =
|
||||
getManualScalingVersionsMap(services);
|
||||
|
||||
// Set number of instances for versions which are manual scaling and non-live
|
||||
manualScalingVersionsMap.forEach(
|
||||
(service, versionId) -> {
|
||||
if (!allLiveVersionsMap.containsEntry(service, versionId)) {
|
||||
setNumInstances(service, versionId, numInstances);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
checkArgument(!services.isEmpty(), "Service must be specified");
|
||||
checkArgument(!versions.isEmpty(), "Version must be specified");
|
||||
checkArgument(numInstances > 0, "Number of instances must be greater than zero");
|
||||
|
||||
ImmutableSetMultimap<Service, String> manualScalingVersionsMap =
|
||||
getManualScalingVersionsMap(services);
|
||||
|
||||
for (Service service : services) {
|
||||
for (String versionId : versions) {
|
||||
checkArgument(
|
||||
manualScalingVersionsMap.containsEntry(service, versionId),
|
||||
"Version %s of service %s is not managed through manual scaling",
|
||||
versionId,
|
||||
service);
|
||||
setNumInstances(service, versionId, numInstances);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setNumInstances(Service service, String version, long numInstances) {
|
||||
appEngineServiceUtils.setNumInstances(service.getServiceId(), version, numInstances);
|
||||
logger.atInfo().log(
|
||||
"Successfully set version %s of service %s to %d instances.",
|
||||
version, service, numInstances);
|
||||
}
|
||||
|
||||
private ImmutableSetMultimap<Service, String> getAllLiveVersionsMap(List<Service> services) {
|
||||
try {
|
||||
return nullToEmpty(appengine.apps().services().list(projectId).execute().getServices())
|
||||
.stream()
|
||||
.filter(
|
||||
service ->
|
||||
services.contains(SERVICE_ID_TO_SERVICE.getOrDefault(service.getId(), null)))
|
||||
.collect(
|
||||
flatteningToImmutableSetMultimap(
|
||||
service -> SERVICE_ID_TO_SERVICE.get(service.getId()),
|
||||
service -> nullToEmpty(service.getSplit().getAllocations()).keySet().stream()));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private ImmutableSetMultimap<Service, String> getManualScalingVersionsMap(
|
||||
List<Service> services) {
|
||||
return services.stream()
|
||||
.collect(
|
||||
flatteningToImmutableSetMultimap(
|
||||
service -> service,
|
||||
service -> {
|
||||
try {
|
||||
return nullToEmpty(
|
||||
appengine
|
||||
.apps()
|
||||
.services()
|
||||
.versions()
|
||||
.list(projectId, service.getServiceId())
|
||||
.execute()
|
||||
.getVersions())
|
||||
.stream()
|
||||
.filter(version -> version.getManualScaling() != null)
|
||||
.map(version -> version.getId());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
|
@ -1,238 +0,0 @@
|
|||
// Copyright 2018 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import google.registry.testing.AppEngineAdminApiHelper;
|
||||
import google.registry.util.AppEngineServiceUtils;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
|
||||
/** Unit tests for {@link SetNumInstancesCommand}. */
|
||||
public class SetNumInstancesCommandTest extends CommandTestCase<SetNumInstancesCommand> {
|
||||
|
||||
@Mock AppEngineServiceUtils appEngineServiceUtils;
|
||||
|
||||
private static final String projectId = "domain-registry-test";
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
command = new SetNumInstancesCommand();
|
||||
command.appEngineServiceUtils = appEngineServiceUtils;
|
||||
command.projectId = projectId;
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_missingService_throwsException() {
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> runCommand("--versions=version", "--num_instances=5"));
|
||||
assertThat(thrown).hasMessageThat().contains("Service must be specified");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_emptyService_throwsException() {
|
||||
ParameterException thrown =
|
||||
assertThrows(
|
||||
ParameterException.class,
|
||||
() -> runCommand("--services=", "--versions=version", "--num_instances=5"));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains(
|
||||
"Invalid value for -s parameter. Allowed values:[DEFAULT, TOOLS, BACKEND, PUBAPI]");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_invalidService_throwsException() {
|
||||
ParameterException thrown =
|
||||
assertThrows(
|
||||
ParameterException.class,
|
||||
() ->
|
||||
runCommand(
|
||||
"--services=INVALID,DEFAULT", "--versions=version", "--num_instances=5"));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains(
|
||||
"Invalid value for -s parameter. Allowed values:[DEFAULT, TOOLS, BACKEND, PUBAPI]");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_missingVersion_throwsException() {
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> runCommand("--services=DEFAULT", "--num_instances=5"));
|
||||
assertThat(thrown).hasMessageThat().contains("Version must be specified");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_emptyVersion_throwsException() {
|
||||
ParameterException thrown =
|
||||
assertThrows(
|
||||
ParameterException.class,
|
||||
() -> runCommand("--services=DEFAULT", "--num_instances=5", "--versions"));
|
||||
assertThat(thrown).hasMessageThat().contains("Expected a value after parameter --versions");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_missingNumInstances_throwsException() {
|
||||
ParameterException thrown =
|
||||
assertThrows(
|
||||
ParameterException.class, () -> runCommand("--services=DEFAULT", "--versions=version"));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains("The following option is required: -n, --num_instances");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_invalidNumInstances_throwsException() {
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> runCommand("--services=DEFAULT", "--versions=version", "--num_instances=-5"));
|
||||
assertThat(thrown).hasMessageThat().contains("Number of instances must be greater than zero");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_versionNotNullWhenSettingAllNonLiveVersions_throwsException() {
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> runCommand("--services=DEFAULT", "--versions=version", "--num_instances=-5"));
|
||||
assertThat(thrown).hasMessageThat().contains("Number of instances must be greater than zero");
|
||||
}
|
||||
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
@Test
|
||||
void test_settingNonManualScalingVersions_throwsException() {
|
||||
command.appengine =
|
||||
new AppEngineAdminApiHelper.Builder()
|
||||
.setAppId(projectId)
|
||||
.setManualScalingVersionsMap(ImmutableMultimap.of("default", "version1"))
|
||||
.build()
|
||||
.getAppengine();
|
||||
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() ->
|
||||
runCommand(
|
||||
"--non_live_versions=true",
|
||||
"--services=DEFAULT",
|
||||
"--versions=version",
|
||||
"--num_instances=10"));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains("--versions cannot be set if --non_live_versions is set");
|
||||
}
|
||||
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
@Test
|
||||
void test_validParameters_succeeds() throws Exception {
|
||||
command.appengine =
|
||||
new AppEngineAdminApiHelper.Builder()
|
||||
.setAppId(projectId)
|
||||
.setManualScalingVersionsMap(ImmutableMultimap.of("default", "version"))
|
||||
.build()
|
||||
.getAppengine();
|
||||
|
||||
runCommand("--services=DEFAULT", "--versions=version", "--num_instances=10");
|
||||
verify(appEngineServiceUtils, times(1)).setNumInstances("default", "version", 10L);
|
||||
}
|
||||
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
@Test
|
||||
void test_validShortParametersAndLowercaseService_succeeds() throws Exception {
|
||||
command.appengine =
|
||||
new AppEngineAdminApiHelper.Builder()
|
||||
.setAppId(projectId)
|
||||
.setManualScalingVersionsMap(ImmutableMultimap.of("default", "version"))
|
||||
.build()
|
||||
.getAppengine();
|
||||
|
||||
runCommand("-s default", "-v version", "-n 10");
|
||||
verify(appEngineServiceUtils, times(1)).setNumInstances("default", "version", 10L);
|
||||
}
|
||||
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
@Test
|
||||
void test_settingMultipleServicesAndVersions_succeeds() throws Exception {
|
||||
command.appengine =
|
||||
new AppEngineAdminApiHelper.Builder()
|
||||
.setAppId(projectId)
|
||||
.setManualScalingVersionsMap(
|
||||
ImmutableMultimap.of(
|
||||
"default", "version1",
|
||||
"default", "version2",
|
||||
"backend", "version1",
|
||||
"backend", "version2"))
|
||||
.build()
|
||||
.getAppengine();
|
||||
|
||||
runCommand("--services=DEFAULT,BACKEND", "--versions=version1,version2", "--num_instances=10");
|
||||
verify(appEngineServiceUtils, times(1)).setNumInstances("default", "version1", 10L);
|
||||
verify(appEngineServiceUtils, times(1)).setNumInstances("default", "version2", 10L);
|
||||
verify(appEngineServiceUtils, times(1)).setNumInstances("backend", "version1", 10L);
|
||||
verify(appEngineServiceUtils, times(1)).setNumInstances("backend", "version2", 10L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_settingAllNonLiveVersions_succeeds() throws Exception {
|
||||
command.appengine =
|
||||
new AppEngineAdminApiHelper.Builder()
|
||||
.setAppId(projectId)
|
||||
.setManualScalingVersionsMap(
|
||||
ImmutableMultimap.of(
|
||||
"default", "version1", "default", "version2", "default", "version3"))
|
||||
.setLiveVersionsMap(ImmutableMultimap.of("default", "version2"))
|
||||
.build()
|
||||
.getAppengine();
|
||||
|
||||
runCommand("--non_live_versions=true", "--services=DEFAULT", "--num_instances=10");
|
||||
verify(appEngineServiceUtils, times(1)).setNumInstances("default", "version1", 10L);
|
||||
verify(appEngineServiceUtils, times(0)).setNumInstances("default", "version2", 10L);
|
||||
verify(appEngineServiceUtils, times(1)).setNumInstances("default", "version3", 10L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_noNonLiveVersions_succeeds() throws Exception {
|
||||
command.appengine =
|
||||
new AppEngineAdminApiHelper.Builder()
|
||||
.setAppId(projectId)
|
||||
.setManualScalingVersionsMap(
|
||||
ImmutableMultimap.of(
|
||||
"default", "version1", "default", "version2", "default", "version3"))
|
||||
.setLiveVersionsMap(
|
||||
ImmutableMultimap.of(
|
||||
"default", "version1", "default", "version2", "default", "version3"))
|
||||
.build()
|
||||
.getAppengine();
|
||||
|
||||
runCommand("--non_live_versions=true", "--services=DEFAULT", "--num_instances=10");
|
||||
verify(appEngineServiceUtils, times(0)).setNumInstances("default", "version1", 10L);
|
||||
verify(appEngineServiceUtils, times(0)).setNumInstances("default", "version2", 10L);
|
||||
verify(appEngineServiceUtils, times(0)).setNumInstances("default", "version3", 10L);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue