// Copyright 2016 The Domain Registry 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.Sets.difference; import static com.google.common.collect.Sets.intersection; import static com.google.common.collect.Sets.union; import static google.registry.model.RoidSuffixes.isRoidSuffixUsed; import static google.registry.util.CollectionUtils.findDuplicates; import static google.registry.util.CollectionUtils.nullToEmpty; import static google.registry.util.DomainNameUtils.canonicalizeDomainName; import com.google.common.base.CharMatcher; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Optional; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedMap; import com.beust.jcommander.Parameter; import com.googlecode.objectify.Key; import google.registry.model.pricing.StaticPremiumListPricingEngine; import google.registry.model.registry.Registries; import google.registry.model.registry.Registry; import google.registry.model.registry.Registry.TldState; import google.registry.model.registry.Registry.TldType; import google.registry.model.registry.label.PremiumList; import google.registry.model.registry.label.ReservedList; import google.registry.tools.params.OptionalStringParameter; import google.registry.tools.params.TransitionListParameter.BillingCostTransitions; import google.registry.tools.params.TransitionListParameter.TldStateTransitions; import org.joda.money.Money; import org.joda.time.DateTime; import org.joda.time.Duration; import java.util.List; import java.util.Set; import javax.annotation.Nullable; /** Shared base class for commands to create or update a TLD. */ abstract class CreateOrUpdateTldCommand extends MutatingCommand { @Parameter( description = "Names of the TLDs", required = true) List mainParameters; @Parameter( names = "--escrow", description = "Whether to enable nightly RDE escrow deposits", arity = 1) private Boolean escrow; @Parameter( names = "--dns", description = "Set to false to pause writing to the DNS queue", arity = 1) private Boolean dns; @Nullable @Parameter( names = "--add_grace_period", description = "Length of the add grace period") Duration addGracePeriod; @Nullable @Parameter( names = "--redemption_grace_period", description = "Length of the redemption grace period") Duration redemptionGracePeriod; @Nullable @Parameter( names = "--pending_delete_length", description = "Length of the pending delete period") Duration pendingDeleteLength; @Nullable @Parameter( names = "--automatic_transfer_length", description = "Length of the automatic transfer period") private Duration automaticTransferLength; @Nullable @Parameter( names = "--restore_billing_cost", description = "One-time billing cost for restoring a domain") private Money restoreBillingCost; @Nullable @Parameter( names = "--roid_suffix", description = "The suffix to be used for ROIDs, e.g. COM for .com domains (which then " + "creates roids looking like 123ABC-COM)") String roidSuffix; @Nullable @Parameter( names = "--server_status_change_cost", description = "One-time billing cost for a server status change") private Money serverStatusChangeCost; @Nullable @Parameter( names = "--tld_type", description = "Tld type (REAL or TEST)") private TldType tldType; @Nullable @Parameter( names = "--premium_price_ack_required", description = "Whether operations on premium domains require explicit ack of prices", arity = 1) private Boolean premiumPriceAckRequired; @Nullable @Parameter( names = "--create_billing_cost", description = "Per-year billing cost for creating a domain") Money createBillingCost; @Nullable @Parameter( names = "--drive_folder_id", description = "Id of the folder in drive used to publish information for this TLD", converter = OptionalStringParameter.class, validateWith = OptionalStringParameter.class) Optional driveFolderId; @Nullable @Parameter( names = "--lordn_username", description = "Username for LORDN uploads", converter = OptionalStringParameter.class, validateWith = OptionalStringParameter.class) Optional lordnUsername; @Nullable @Parameter( names = "--premium_list", description = "The name of the premium list to apply to the TLD", converter = OptionalStringParameter.class, validateWith = OptionalStringParameter.class) Optional premiumListName; @Parameter( names = "--tld_state_transitions", converter = TldStateTransitions.class, validateWith = TldStateTransitions.class, description = "Comma-delimited list of TLD state transitions, of the form " + "