mirror of
https://github.com/google/nomulus
synced 2026-05-22 07:41:50 +00:00
Compare commits
4 Commits
nomulus-20
...
nomulus-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac14688a4f | ||
|
|
7ab572188a | ||
|
|
2f438b1d3a | ||
|
|
0d3c0f7b76 |
@@ -13,11 +13,11 @@
|
||||
// limitations under the License.
|
||||
package google.registry.batch;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.primitives.Ints;
|
||||
@@ -25,7 +25,6 @@ import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.domain.token.PackagePromotion;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Action.Service;
|
||||
import google.registry.request.auth.Auth;
|
||||
@@ -88,10 +87,10 @@ public class CheckPackagesComplianceAction implements Runnable {
|
||||
|
||||
private void checkPackages() {
|
||||
ImmutableList<PackagePromotion> packages = tm().loadAllOf(PackagePromotion.class);
|
||||
ImmutableList.Builder<PackagePromotion> packagesOverCreateLimitBuilder =
|
||||
new ImmutableList.Builder<>();
|
||||
ImmutableList.Builder<PackagePromotion> packagesOverActiveDomainsLimitBuilder =
|
||||
new ImmutableList.Builder<>();
|
||||
ImmutableMap.Builder<PackagePromotion, Long> packagesOverCreateLimitBuilder =
|
||||
new ImmutableMap.Builder<>();
|
||||
ImmutableMap.Builder<PackagePromotion, Long> packagesOverActiveDomainsLimitBuilder =
|
||||
new ImmutableMap.Builder<>();
|
||||
for (PackagePromotion packagePromo : packages) {
|
||||
Long creates =
|
||||
(Long)
|
||||
@@ -103,12 +102,12 @@ public class CheckPackagesComplianceAction implements Runnable {
|
||||
.setParameter("lastBilling", packagePromo.getNextBillingDate().minusYears(1))
|
||||
.getSingleResult();
|
||||
if (creates > packagePromo.getMaxCreates()) {
|
||||
int overage = Ints.saturatedCast(creates) - packagePromo.getMaxCreates();
|
||||
long overage = creates - packagePromo.getMaxCreates();
|
||||
logger.atInfo().log(
|
||||
"Package with package token %s has exceeded their max domain creation limit"
|
||||
+ " by %d name(s).",
|
||||
packagePromo.getToken().getKey(), overage);
|
||||
packagesOverCreateLimitBuilder.add(packagePromo);
|
||||
packagesOverCreateLimitBuilder.put(packagePromo, creates);
|
||||
}
|
||||
|
||||
Long activeDomains =
|
||||
@@ -125,20 +124,20 @@ public class CheckPackagesComplianceAction implements Runnable {
|
||||
"Package with package token %s has exceed their max active domains limit by"
|
||||
+ " %d name(s).",
|
||||
packagePromo.getToken().getKey(), overage);
|
||||
packagesOverActiveDomainsLimitBuilder.add(packagePromo);
|
||||
packagesOverActiveDomainsLimitBuilder.put(packagePromo, activeDomains);
|
||||
}
|
||||
}
|
||||
handlePackageCreationOverage(packagesOverCreateLimitBuilder.build());
|
||||
handleActiveDomainOverage(packagesOverActiveDomainsLimitBuilder.build());
|
||||
}
|
||||
|
||||
private void handlePackageCreationOverage(ImmutableList<PackagePromotion> overageList) {
|
||||
private void handlePackageCreationOverage(ImmutableMap<PackagePromotion, Long> overageList) {
|
||||
if (overageList.isEmpty()) {
|
||||
logger.atInfo().log("Found no packages over their create limit.");
|
||||
return;
|
||||
}
|
||||
logger.atInfo().log("Found %d packages over their create limit.", overageList.size());
|
||||
for (PackagePromotion packagePromotion : overageList) {
|
||||
for (PackagePromotion packagePromotion : overageList.keySet()) {
|
||||
AllocationToken packageToken = tm().loadByKey(packagePromotion.getToken());
|
||||
Optional<Registrar> registrar =
|
||||
Registrar.loadByRegistrarIdCached(
|
||||
@@ -147,9 +146,11 @@ public class CheckPackagesComplianceAction implements Runnable {
|
||||
String body =
|
||||
String.format(
|
||||
packageCreateLimitEmailBody,
|
||||
registrar.get().getRegistrarName(),
|
||||
packagePromotion.getId(),
|
||||
packageToken.getToken(),
|
||||
registrySupportEmail);
|
||||
registrar.get().getRegistrarName(),
|
||||
packagePromotion.getMaxCreates(),
|
||||
overageList.get(packagePromotion));
|
||||
sendNotification(packageToken, packageCreateLimitEmailSubject, body, registrar.get());
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
@@ -158,13 +159,13 @@ public class CheckPackagesComplianceAction implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleActiveDomainOverage(ImmutableList<PackagePromotion> overageList) {
|
||||
private void handleActiveDomainOverage(ImmutableMap<PackagePromotion, Long> overageList) {
|
||||
if (overageList.isEmpty()) {
|
||||
logger.atInfo().log("Found no packages over their active domains limit.");
|
||||
return;
|
||||
}
|
||||
logger.atInfo().log("Found %d packages over their active domains limit.", overageList.size());
|
||||
for (PackagePromotion packagePromotion : overageList) {
|
||||
for (PackagePromotion packagePromotion : overageList.keySet()) {
|
||||
int daysSinceLastNotification =
|
||||
packagePromotion
|
||||
.getLastNotificationSent()
|
||||
@@ -176,15 +177,18 @@ public class CheckPackagesComplianceAction implements Runnable {
|
||||
continue;
|
||||
} else if (daysSinceLastNotification < FORTY_DAYS) {
|
||||
// Send an upgrade email if last email was between 30 and 40 days ago
|
||||
sendActiveDomainOverageEmail(/* warning= */ false, packagePromotion);
|
||||
sendActiveDomainOverageEmail(
|
||||
/* warning= */ false, packagePromotion, overageList.get(packagePromotion));
|
||||
} else {
|
||||
// Send a warning email
|
||||
sendActiveDomainOverageEmail(/* warning= */ true, packagePromotion);
|
||||
sendActiveDomainOverageEmail(
|
||||
/* warning= */ true, packagePromotion, overageList.get(packagePromotion));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendActiveDomainOverageEmail(boolean warning, PackagePromotion packagePromotion) {
|
||||
private void sendActiveDomainOverageEmail(
|
||||
boolean warning, PackagePromotion packagePromotion, long activeDomains) {
|
||||
String emailSubject =
|
||||
warning ? packageDomainLimitWarningEmailSubject : packageDomainLimitUpgradeEmailSubject;
|
||||
String emailTemplate =
|
||||
@@ -197,9 +201,11 @@ public class CheckPackagesComplianceAction implements Runnable {
|
||||
String body =
|
||||
String.format(
|
||||
emailTemplate,
|
||||
registrar.get().getRegistrarName(),
|
||||
packagePromotion.getId(),
|
||||
packageToken.getToken(),
|
||||
registrySupportEmail);
|
||||
registrar.get().getRegistrarName(),
|
||||
packagePromotion.getMaxDomains(),
|
||||
activeDomains);
|
||||
sendNotification(packageToken, emailSubject, body, registrar.get());
|
||||
tm().put(packagePromotion.asBuilder().setLastNotificationSent(clock.nowUtc()).build());
|
||||
} else {
|
||||
@@ -212,15 +218,9 @@ public class CheckPackagesComplianceAction implements Runnable {
|
||||
AllocationToken packageToken, String subject, String body, Registrar registrar) {
|
||||
logger.atInfo().log(
|
||||
String.format(
|
||||
"Compliance email sent to the %s registrar regarding the package with token" + " %s.",
|
||||
"Compliance email sent to support regarding the %s registrar and the package with token"
|
||||
+ " %s.",
|
||||
registrar.getRegistrarName(), packageToken.getToken()));
|
||||
sendEmailUtils.sendEmail(
|
||||
subject,
|
||||
body,
|
||||
Optional.of(registrySupportEmail),
|
||||
registrar.getContacts().stream()
|
||||
.filter(c -> c.getTypes().contains(RegistrarPoc.Type.ADMIN))
|
||||
.map(RegistrarPoc::getEmailAddress)
|
||||
.collect(toImmutableList()));
|
||||
sendEmailUtils.sendEmail(subject, body, ImmutableList.of(registrySupportEmail));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -538,52 +538,53 @@ sslCertificateValidation:
|
||||
|
||||
# Configuration options for the package compliance monitoring
|
||||
packageMonitoring:
|
||||
# Email subject text to notify partners their package has exceeded the limit for domain creates
|
||||
packageCreateLimitEmailSubject: "NOTICE: Your package is being upgraded"
|
||||
# Email body text template notify partners their package has exceeded the limit for domain creates
|
||||
# Email subject text to notify tech support that a package has exceeded the limit for domain creates
|
||||
packageCreateLimitEmailSubject: "ACTION REQUIRED: Package needs to be upgraded"
|
||||
# Email body text template notify support that a package has exceeded the limit for domain creates
|
||||
packageCreateLimitEmailBody: >
|
||||
Dear %1$s,
|
||||
Dear Support,
|
||||
|
||||
We are contacting you to inform you that your package with the package token
|
||||
%2$s has exceeded its limit for annual domain creations.
|
||||
Your package will now be upgraded to the next tier.
|
||||
A package has exceeded its max create limit and needs to be upgraded to the
|
||||
next tier.
|
||||
|
||||
If you have any questions or require additional support, please contact us
|
||||
at %3$s.
|
||||
|
||||
Regards,
|
||||
Example Registry
|
||||
Package ID: %1$s
|
||||
Package Token: %2$s
|
||||
Registrar: %3$s
|
||||
Current Max Create Limit: %4$s
|
||||
Creates Completed: %5$s
|
||||
|
||||
# Email subject text to notify partners their package has exceeded the limit for current active domains and warn them their package will be upgraded in 30 days
|
||||
packageDomainLimitWarningEmailSubject: "WARNING: Your package has exceeded the domain limit"
|
||||
# Email body text template to warn partners their package has exceeded the limit for active domains and will be upgraded in 30 days
|
||||
# Email subject text to notify support that a package has exceeded the limit
|
||||
# for current active domains and a warning needs to be sent
|
||||
packageDomainLimitWarningEmailSubject: "ACTION REQUIRED: Package has exceeded the domain limit - send warning"
|
||||
# Email body text template to inform support that a package has exceeded the
|
||||
# limit for active domains and a warning needs to be sent that the package
|
||||
# will be upgraded in 30 days
|
||||
packageDomainLimitWarningEmailBody: >
|
||||
Dear %1$s,
|
||||
|
||||
We are contacting you to inform you that your package with the package token
|
||||
%2$s has exceeded its limit for active domains.
|
||||
Your package will be upgraded to the next tier in 30 days if the number of active domains does not return below the limit.
|
||||
|
||||
If you have any questions or require additional support, please contact us
|
||||
at %3$s.
|
||||
|
||||
Regards,
|
||||
Example Registry
|
||||
|
||||
# Email subject text to notify partners their package has exceeded the limit
|
||||
# for current active domains for more than 30 days and will be upgraded
|
||||
packageDomainLimitUpgradeEmailSubject: "NOTICE: Your package is being upgraded"
|
||||
# Email body text template to warn partners their package has exceeded the
|
||||
# limit for active domains for more than 30 days and will be upgraded
|
||||
packageDomainLimitUpgradeEmailBody: >
|
||||
Dear %1$s,
|
||||
Dear Support,
|
||||
|
||||
We are contacting you to inform you that your package with the package token
|
||||
%2$s has exceeded its limit for active domains.
|
||||
Your package will now be upgraded to the next tier.
|
||||
A package has exceeded its max domain limit. Please send a warning to the
|
||||
registrar that their package will be upgraded to the next tier in 30 days if
|
||||
the number of active domains does not return below the limit.
|
||||
|
||||
Package ID: %1$s
|
||||
Package Token: %2$s
|
||||
Registrar: %3$s
|
||||
Active Domain Limit: %4$s
|
||||
Current Active Domains: %5$s
|
||||
|
||||
If you have any questions or require additional support, please contact us
|
||||
at %3$s.
|
||||
|
||||
Regards,
|
||||
Example Registry
|
||||
# Email subject text to notify support that a package has exceeded the limit
|
||||
# for current active domains for more than 30 days and needs to be upgraded
|
||||
packageDomainLimitUpgradeEmailSubject: "ACTION REQUIRED: Package has exceeded the domain limit - upgrade package"
|
||||
# Email body text template to inform support that a package has exceeded the
|
||||
# limit for active domains for more than 30 days and needs to be upgraded
|
||||
packageDomainLimitUpgradeEmailBody: >
|
||||
Dear Support,
|
||||
|
||||
A package has exceeded its max domain limit for over 30 days and needs to be
|
||||
upgraded to the next tier.
|
||||
|
||||
Package ID: %1$s
|
||||
Package Token: %2$s
|
||||
Registrar: %3$s
|
||||
Active Domain Limit: %4$s
|
||||
Current Active Domains: %5$s
|
||||
|
||||
@@ -74,6 +74,10 @@ public class PackagePromotion extends ImmutableObject implements Buildable {
|
||||
/** Date the last warning email was sent that the package has exceeded the maxDomains limit. */
|
||||
@Nullable DateTime lastNotificationSent;
|
||||
|
||||
public long getId() {
|
||||
return packagePromotionId;
|
||||
}
|
||||
|
||||
public VKey<AllocationToken> getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ package google.registry.monitoring.whitebox;
|
||||
|
||||
import com.google.api.services.monitoring.v3.Monitoring;
|
||||
import com.google.api.services.monitoring.v3.model.MonitoredResource;
|
||||
import com.google.appengine.api.modules.ModulesService;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.google.monitoring.metrics.MetricReporter;
|
||||
@@ -34,8 +33,9 @@ import org.joda.time.Duration;
|
||||
public final class StackdriverModule {
|
||||
|
||||
// We need a fake GCE zone to appease Stackdriver's resource model.
|
||||
// TODO(b/31021585): Revisit this if/when gae_instance exists.
|
||||
// TODO(b/265973059): Switch to resource type "gke_container".
|
||||
private static final String SPOOFED_GCE_ZONE = "us-central1-f";
|
||||
private static final String SPOOFED_GCE_INSTANCE = "fake-instance";
|
||||
|
||||
@Provides
|
||||
static Monitoring provideMonitoring(
|
||||
@@ -53,7 +53,6 @@ public final class StackdriverModule {
|
||||
static MetricWriter provideMetricWriter(
|
||||
Monitoring monitoringClient,
|
||||
@Config("projectId") String projectId,
|
||||
ModulesService modulesService,
|
||||
@Config("stackdriverMaxQps") int maxQps,
|
||||
@Config("stackdriverMaxPointsPerRequest") int maxPointsPerRequest) {
|
||||
// The MonitoredResource for GAE apps is not writable (and missing fields anyway) so we just
|
||||
@@ -66,16 +65,7 @@ public final class StackdriverModule {
|
||||
.setLabels(
|
||||
ImmutableMap.of(
|
||||
// The "zone" field MUST be a valid GCE zone, so we fake one.
|
||||
"zone",
|
||||
SPOOFED_GCE_ZONE,
|
||||
// Overload the GCE "instance_id" field with the GAE module name, version and
|
||||
// instance_id.
|
||||
"instance_id",
|
||||
modulesService.getCurrentModule()
|
||||
+ ":"
|
||||
+ modulesService.getCurrentVersion()
|
||||
+ ":"
|
||||
+ modulesService.getCurrentInstanceId())),
|
||||
"zone", SPOOFED_GCE_ZONE, "instance_id", SPOOFED_GCE_INSTANCE)),
|
||||
maxQps,
|
||||
maxPointsPerRequest);
|
||||
}
|
||||
|
||||
@@ -60,11 +60,12 @@ public class CheckPackagesComplianceActionTest {
|
||||
private static final String CREATE_LIMIT_EMAIL_SUBJECT = "create limit subject";
|
||||
private static final String DOMAIN_LIMIT_WARNING_EMAIL_SUBJECT = "domain limit warning subject";
|
||||
private static final String DOMAIN_LIMIT_UPGRADE_EMAIL_SUBJECT = "domain limit upgrade subject";
|
||||
private static final String CREATE_LIMIT_EMAIL_BODY = "create limit body %1$s %2$s %3$s";
|
||||
private static final String CREATE_LIMIT_EMAIL_BODY =
|
||||
"create limit body %1$s %2$s %3$s %4$s %5$s";
|
||||
private static final String DOMAIN_LIMIT_WARNING_EMAIL_BODY =
|
||||
"domain limit warning body %1$s %2$s %3$s";
|
||||
"domain limit warning body %1$s %2$s %3$s %4$s %5$s";
|
||||
private static final String DOMAIN_LIMIT_UPGRADE_EMAIL_BODY =
|
||||
"domain limit upgrade body %1$s %2$s %3$s";
|
||||
"domain limit upgrade body %1$s %2$s %3$s %4$s %5$s";
|
||||
private static final String SUPPORT_EMAIL = "registry@test.com";
|
||||
|
||||
@RegisterExtension
|
||||
@@ -177,8 +178,7 @@ public class CheckPackagesComplianceActionTest {
|
||||
EmailMessage emailMessage = emailCaptor.getValue();
|
||||
assertThat(emailMessage.subject()).isEqualTo(CREATE_LIMIT_EMAIL_SUBJECT);
|
||||
assertThat(emailMessage.body())
|
||||
.isEqualTo(
|
||||
String.format(CREATE_LIMIT_EMAIL_BODY, "The Registrar", "abc123", SUPPORT_EMAIL));
|
||||
.isEqualTo(String.format(CREATE_LIMIT_EMAIL_BODY, 1, "abc123", "The Registrar", 1, 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -364,8 +364,7 @@ public class CheckPackagesComplianceActionTest {
|
||||
assertThat(emailMessage.subject()).isEqualTo(DOMAIN_LIMIT_WARNING_EMAIL_SUBJECT);
|
||||
assertThat(emailMessage.body())
|
||||
.isEqualTo(
|
||||
String.format(
|
||||
DOMAIN_LIMIT_WARNING_EMAIL_BODY, "The Registrar", "abc123", SUPPORT_EMAIL));
|
||||
String.format(DOMAIN_LIMIT_WARNING_EMAIL_BODY, 1, "abc123", "The Registrar", 1, 2));
|
||||
PackagePromotion packageAfterCheck =
|
||||
tm().transact(() -> PackagePromotion.loadByTokenString(token.getToken()).get());
|
||||
assertThat(packageAfterCheck.getLastNotificationSent().get()).isEqualTo(clock.nowUtc());
|
||||
@@ -514,8 +513,7 @@ public class CheckPackagesComplianceActionTest {
|
||||
assertThat(emailMessage.subject()).isEqualTo(DOMAIN_LIMIT_WARNING_EMAIL_SUBJECT);
|
||||
assertThat(emailMessage.body())
|
||||
.isEqualTo(
|
||||
String.format(
|
||||
DOMAIN_LIMIT_WARNING_EMAIL_BODY, "The Registrar", "abc123", SUPPORT_EMAIL));
|
||||
String.format(DOMAIN_LIMIT_WARNING_EMAIL_BODY, 1, "abc123", "The Registrar", 1, 2));
|
||||
PackagePromotion packageAfterCheck =
|
||||
tm().transact(() -> PackagePromotion.loadByTokenString(token.getToken()).get());
|
||||
assertThat(packageAfterCheck.getLastNotificationSent().get()).isEqualTo(clock.nowUtc());
|
||||
@@ -558,8 +556,7 @@ public class CheckPackagesComplianceActionTest {
|
||||
assertThat(emailMessage.subject()).isEqualTo(DOMAIN_LIMIT_UPGRADE_EMAIL_SUBJECT);
|
||||
assertThat(emailMessage.body())
|
||||
.isEqualTo(
|
||||
String.format(
|
||||
DOMAIN_LIMIT_UPGRADE_EMAIL_BODY, "The Registrar", "abc123", SUPPORT_EMAIL));
|
||||
String.format(DOMAIN_LIMIT_UPGRADE_EMAIL_BODY, 1, "abc123", "The Registrar", 1, 2));
|
||||
PackagePromotion packageAfterCheck =
|
||||
tm().transact(() -> PackagePromotion.loadByTokenString(token.getToken()).get());
|
||||
assertThat(packageAfterCheck.getLastNotificationSent().get()).isEqualTo(clock.nowUtc());
|
||||
|
||||
@@ -22,7 +22,8 @@ import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
|
||||
import com.google.appengine.tools.development.testing.LocalTaskQueueTestConfig;
|
||||
import com.google.apphosting.api.ApiProxy;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
@@ -39,26 +40,22 @@ public final class TaskQueueExtension implements BeforeEachCallback, AfterEachCa
|
||||
readResourceUtf8("google/registry/env/common/default/WEB-INF/queue.xml");
|
||||
|
||||
private LocalServiceTestHelper helper;
|
||||
private String taskQueueXml;
|
||||
private File tmpDir;
|
||||
|
||||
public TaskQueueExtension() {
|
||||
this.taskQueueXml = QUEUE_XML;
|
||||
}
|
||||
private Path queueFile;
|
||||
|
||||
@Override
|
||||
public void beforeEach(ExtensionContext context) throws Exception {
|
||||
File queueFile = new File(tmpDir, "queue.xml");
|
||||
asCharSink(queueFile, UTF_8).write(taskQueueXml);
|
||||
queueFile = Files.createTempFile("queue", ".xml");
|
||||
asCharSink(queueFile.toFile(), UTF_8).write(QUEUE_XML);
|
||||
helper =
|
||||
new LocalServiceTestHelper(
|
||||
new LocalTaskQueueTestConfig().setQueueXmlPath(queueFile.getAbsolutePath()));
|
||||
new LocalTaskQueueTestConfig().setQueueXmlPath(queueFile.toAbsolutePath().toString()));
|
||||
helper.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterEach(ExtensionContext context) throws Exception {
|
||||
helper.tearDown();
|
||||
Files.delete(queueFile);
|
||||
ApiProxy.setEnvironmentForCurrentThread(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ steps:
|
||||
fi
|
||||
gsutil cp gs://$PROJECT_ID-deploy/${TAG_NAME}/${_ENV}.tar .
|
||||
tar -xvf ${_ENV}.tar
|
||||
for filename in cron dispatch index queue; do
|
||||
for filename in cron dispatch queue; do
|
||||
gcloud -q --project $project_id app deploy \
|
||||
default/WEB-INF/appengine-generated/$filename.yaml
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user