mv com/google/domain/registry google/registry

This change renames directories in preparation for the great package
rename. The repository is now in a broken state because the code
itself hasn't been updated. However this should ensure that git
correctly preserves history for each file.
This commit is contained in:
Justine Tunney 2016-05-13 18:55:08 -04:00
parent a41677aea1
commit 5012893c1d
2396 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,82 @@
// 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 com.google.domain.registry.flows.host;
import static com.google.domain.registry.model.eppoutput.CheckData.HostCheck.create;
import static com.google.domain.registry.testing.DatastoreHelper.persistActiveHost;
import static com.google.domain.registry.testing.DatastoreHelper.persistDeletedHost;
import com.google.domain.registry.flows.ResourceCheckFlow.TooManyResourceChecksException;
import com.google.domain.registry.flows.ResourceCheckFlowTestCase;
import com.google.domain.registry.model.host.HostResource;
import org.junit.Test;
/** Unit tests for {@link HostCheckFlow}. */
public class HostCheckFlowTest extends ResourceCheckFlowTestCase<HostCheckFlow, HostResource> {
public HostCheckFlowTest() {
setEppInput("host_check.xml");
}
@Test
public void testNothingExists() throws Exception {
// These ids come from the check xml.
doCheckTest(
create(true, "ns1.example.tld", null),
create(true, "ns2.example.tld", null),
create(true, "ns3.example.tld", null));
}
@Test
public void testOneExists() throws Exception {
persistActiveHost("ns1.example.tld");
// These ids come from the check xml.
doCheckTest(
create(false, "ns1.example.tld", "In use"),
create(true, "ns2.example.tld", null),
create(true, "ns3.example.tld", null));
}
@Test
public void testOneExistsButWasDeleted() throws Exception {
persistDeletedHost("ns1.example.tld", clock.nowUtc());
// These ids come from the check xml.
doCheckTest(
create(true, "ns1.example.tld", null),
create(true, "ns2.example.tld", null),
create(true, "ns3.example.tld", null));
}
@Test
public void testXmlMatches() throws Exception {
persistActiveHost("ns2.example.tld");
runFlowAssertResponse(readFile("host_check_response.xml"));
}
@Test
public void test50IdsAllowed() throws Exception {
// Make sure we don't have a regression that reduces the number of allowed checks.
setEppInput("host_check_50.xml");
runFlow();
}
@Test
public void testTooManyIds() throws Exception {
setEppInput("host_check_51.xml");
thrown.expect(TooManyResourceChecksException.class);
runFlow();
}
}

View file

@ -0,0 +1,236 @@
// 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 com.google.domain.registry.flows.host;
import static com.google.common.truth.Truth.assertThat;
import static com.google.domain.registry.model.ofy.ObjectifyService.ofy;
import static com.google.domain.registry.testing.DatastoreHelper.assertNoBillingEvents;
import static com.google.domain.registry.testing.DatastoreHelper.createTld;
import static com.google.domain.registry.testing.DatastoreHelper.persistActiveDomain;
import static com.google.domain.registry.testing.DatastoreHelper.persistActiveHost;
import static com.google.domain.registry.testing.DatastoreHelper.persistDeletedHost;
import static com.google.domain.registry.testing.HostResourceSubject.assertAboutHosts;
import static com.google.domain.registry.testing.TaskQueueHelper.assertDnsTasksEnqueued;
import static com.google.domain.registry.testing.TaskQueueHelper.assertNoDnsTasksEnqueued;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.domain.registry.flows.EppXmlTransformer.IpAddressVersionMismatchException;
import com.google.domain.registry.flows.ResourceCreateFlow.ResourceAlreadyExistsException;
import com.google.domain.registry.flows.ResourceFlowTestCase;
import com.google.domain.registry.flows.host.HostCreateFlow.SubordinateHostMustHaveIpException;
import com.google.domain.registry.flows.host.HostCreateFlow.UnexpectedExternalHostIpException;
import com.google.domain.registry.flows.host.HostFlowUtils.HostNameTooLongException;
import com.google.domain.registry.flows.host.HostFlowUtils.HostNameTooShallowException;
import com.google.domain.registry.flows.host.HostFlowUtils.InvalidHostNameException;
import com.google.domain.registry.flows.host.HostFlowUtils.SuperordinateDomainDoesNotExistException;
import com.google.domain.registry.model.host.HostResource;
import com.google.domain.registry.model.reporting.HistoryEntry;
import org.joda.time.DateTime;
import org.junit.Before;
import org.junit.Test;
/** Unit tests for {@link HostCreateFlow}. */
public class HostCreateFlowTest extends ResourceFlowTestCase<HostCreateFlow, HostResource> {
private void setEppHostCreateInput(String hostName, String hostAddrs) {
setEppInput(
"host_create.xml",
ImmutableMap.of(
"HOSTNAME", hostName,
"HOSTADDRS", (hostAddrs == null) ? "" : hostAddrs));
}
private void setEppHostCreateInputWithIps(String hostName) {
setEppHostCreateInput(
hostName,
"<host:addr ip=\"v4\">192.0.2.2</host:addr>\n"
+ "<host:addr ip=\"v4\">192.0.2.29</host:addr>\n"
+ "<host:addr ip=\"v6\">1080:0:0:0:8:800:200C:417A</host:addr>");
}
public HostCreateFlowTest() {
setEppHostCreateInput("ns1.example.tld", null);
clock.setTo(DateTime.parse("1999-04-03T22:00:00.0Z"));
}
@Before
public void initHostTest() {
createTld("foobar");
}
private void doSuccessfulTest() throws Exception {
clock.advanceOneMilli();
assertTransactionalFlow(true);
runFlowAssertResponse(readFile("host_create_response.xml"));
// Check that the host was created and persisted with a history entry.
assertAboutHosts().that(reloadResourceByUniqueId())
.hasOnlyOneHistoryEntryWhich()
.hasType(HistoryEntry.Type.HOST_CREATE);
assertNoBillingEvents();
assertEppResourceIndexEntityFor(reloadResourceByUniqueId());
}
private void doSuccessfulInternalTest(String tld) throws Exception {
setEppHostCreateInputWithIps("ns1.example.tld");
createTld(tld);
persistActiveDomain("example.tld");
doSuccessfulTest();
}
@Test
public void testDryRun() throws Exception {
dryRunFlowAssertResponse(readFile("host_create_response.xml"));
}
@Test
public void testSuccess_externalNeverExisted() throws Exception {
doSuccessfulTest();
assertNoDnsTasksEnqueued();
}
@Test
public void testSuccess_internalNeverExisted() throws Exception {
doSuccessfulInternalTest("tld");
assertThat(ofy().load().ref(reloadResourceByUniqueId().getSuperordinateDomain())
.now().getFullyQualifiedDomainName())
.isEqualTo("example.tld");
assertThat(ofy().load().ref(reloadResourceByUniqueId().getSuperordinateDomain())
.now().getSubordinateHosts()).containsExactly("ns1.example.tld");
assertDnsTasksEnqueued("ns1.example.tld");
}
@Test
public void testSuccess_externalExistedButWasDeleted() throws Exception {
persistDeletedHost(getUniqueIdFromCommand(), clock.nowUtc());
doSuccessfulTest();
assertNoDnsTasksEnqueued();
}
@Test
public void testSuccess_internalExistedButWasDeleted() throws Exception {
persistDeletedHost(getUniqueIdFromCommand(), clock.nowUtc());
doSuccessfulInternalTest("tld");
assertThat(ofy().load().ref(reloadResourceByUniqueId().getSuperordinateDomain())
.now().getFullyQualifiedDomainName())
.isEqualTo("example.tld");
assertThat(ofy().load().ref(reloadResourceByUniqueId().getSuperordinateDomain())
.now().getSubordinateHosts()).containsExactly("ns1.example.tld");
assertDnsTasksEnqueued("ns1.example.tld");
}
@Test
public void testFailure_subordinateNeedsIps() throws Exception {
setEppHostCreateInput("ns1.example.tld", null);
createTld("tld");
persistActiveDomain("example.tld");
thrown.expect(SubordinateHostMustHaveIpException.class);
runFlow();
}
@Test
public void testFailure_externalMustNotHaveIps() throws Exception {
setEppHostCreateInputWithIps("ns1.example.external");
createTld("tld");
persistActiveDomain("example.tld");
thrown.expect(UnexpectedExternalHostIpException.class);
runFlow();
}
@Test
public void testFailure_superordinateMissing() throws Exception {
setEppHostCreateInput("ns1.example.tld", null);
createTld("tld");
thrown.expect(
SuperordinateDomainDoesNotExistException.class,
"(example.tld)");
runFlow();
}
@Test
public void testFailure_alreadyExists() throws Exception {
setEppHostCreateInput("ns1.example.tld", null);
persistActiveHost(getUniqueIdFromCommand());
thrown.expect(
ResourceAlreadyExistsException.class,
String.format("Object with given ID (%s) already exists", getUniqueIdFromCommand()));
runFlow();
}
@Test
public void testFailure_longHostName() throws Exception {
setEppHostCreateInputWithIps("a" + Strings.repeat(".labelpart", 25) + ".tld");
thrown.expect(HostNameTooLongException.class);
runFlow();
}
@Test
public void testFailure_ip4AddressWithIp6Declaration() throws Exception {
setEppHostCreateInput(
"ns1.example.tld",
"<host:addr ip=\"v4\">192.0.2.2</host:addr>\n"
+ "<host:addr ip=\"v6\">192.0.2.29</host:addr>\n"
+ "<host:addr ip=\"v6\">1080:0:0:0:8:800:200C:417A</host:addr>");
thrown.expect(IpAddressVersionMismatchException.class);
runFlow();
}
private void doFailingHostNameTest(
String hostName,
Class<? extends Throwable> exception) throws Exception {
setEppHostCreateInputWithIps(hostName);
thrown.expect(exception);
runFlow();
}
@Test
public void testFailure_badCharacter() throws Exception {
doFailingHostNameTest("foo bar", InvalidHostNameException.class);
}
@Test
public void testFailure_tooShallowPublicSuffix() throws Exception {
doFailingHostNameTest("example.tld", HostNameTooShallowException.class);
}
@Test
public void testFailure_tooShallowCcTld() throws Exception {
doFailingHostNameTest("foo.co.uk", HostNameTooShallowException.class);
}
@Test
public void testFailure_barePublicSuffix() throws Exception {
doFailingHostNameTest("com", HostNameTooShallowException.class);
}
@Test
public void testFailure_bareCcTld() throws Exception {
doFailingHostNameTest("co.uk", HostNameTooShallowException.class);
}
@Test
public void testFailure_tooShallowNewTld() throws Exception {
doFailingHostNameTest("example.lol", HostNameTooShallowException.class);
}
@Test
public void testFailure_ccTldInBailiwick() throws Exception {
createTld("co.uk");
setEppHostCreateInputWithIps("foo.co.uk");
thrown.expect(HostNameTooShallowException.class);
runFlow();
}
}

View file

@ -0,0 +1,197 @@
// 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 com.google.domain.registry.flows.host;
import static com.google.domain.registry.flows.async.AsyncFlowUtils.ASYNC_FLOW_QUEUE_NAME;
import static com.google.domain.registry.request.Actions.getPathForAction;
import static com.google.domain.registry.testing.DatastoreHelper.assertNoBillingEvents;
import static com.google.domain.registry.testing.DatastoreHelper.createTld;
import static com.google.domain.registry.testing.DatastoreHelper.newDomainApplication;
import static com.google.domain.registry.testing.DatastoreHelper.newDomainResource;
import static com.google.domain.registry.testing.DatastoreHelper.newHostResource;
import static com.google.domain.registry.testing.DatastoreHelper.persistActiveHost;
import static com.google.domain.registry.testing.DatastoreHelper.persistDeletedHost;
import static com.google.domain.registry.testing.DatastoreHelper.persistResource;
import static com.google.domain.registry.testing.HostResourceSubject.assertAboutHosts;
import static com.google.domain.registry.testing.TaskQueueHelper.assertNoDnsTasksEnqueued;
import static com.google.domain.registry.testing.TaskQueueHelper.assertTasksEnqueued;
import com.google.common.collect.ImmutableSet;
import com.google.domain.registry.flows.FlowRunner.CommitMode;
import com.google.domain.registry.flows.FlowRunner.UserPrivileges;
import com.google.domain.registry.flows.ResourceAsyncDeleteFlow.ResourceToDeleteIsReferencedException;
import com.google.domain.registry.flows.ResourceFlowTestCase;
import com.google.domain.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
import com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException;
import com.google.domain.registry.flows.SingleResourceFlow.ResourceStatusProhibitsOperationException;
import com.google.domain.registry.flows.async.DeleteEppResourceAction;
import com.google.domain.registry.flows.async.DeleteHostResourceAction;
import com.google.domain.registry.model.domain.ReferenceUnion;
import com.google.domain.registry.model.eppcommon.StatusValue;
import com.google.domain.registry.model.host.HostResource;
import com.google.domain.registry.model.reporting.HistoryEntry;
import com.google.domain.registry.testing.TaskQueueHelper.TaskMatcher;
import com.googlecode.objectify.Key;
import org.joda.time.Duration;
import org.junit.Before;
import org.junit.Test;
/** Unit tests for {@link HostDeleteFlow}. */
public class HostDeleteFlowTest extends ResourceFlowTestCase<HostDeleteFlow, HostResource> {
@Before
public void initFlowTest() {
setEppInput("host_delete.xml");
}
private void doFailingStatusTest(StatusValue statusValue, Class<? extends Exception> exception)
throws Exception {
thrown.expect(exception);
persistResource(
newHostResource(getUniqueIdFromCommand()).asBuilder()
.setStatusValues(ImmutableSet.of(statusValue))
.build());
runFlow();
}
@Test
public void testDryRun() throws Exception {
persistActiveHost(getUniqueIdFromCommand());
dryRunFlowAssertResponse(readFile("host_delete_response.xml"));
}
@Test
public void testSuccess() throws Exception {
persistActiveHost(getUniqueIdFromCommand());
clock.advanceOneMilli();
assertTransactionalFlow(true);
runFlowAssertResponse(readFile("host_delete_response.xml"));
HostResource deletedHost = reloadResourceByUniqueId();
assertAboutHosts().that(deletedHost).hasStatusValue(StatusValue.PENDING_DELETE);
assertTasksEnqueued(ASYNC_FLOW_QUEUE_NAME, new TaskMatcher()
.url(getPathForAction(DeleteHostResourceAction.class))
.etaDelta(Duration.standardSeconds(75), Duration.standardSeconds(105)) // expected: 90
.param(
DeleteEppResourceAction.PARAM_REQUESTING_CLIENT_ID,
"TheRegistrar")
.param(
DeleteEppResourceAction.PARAM_IS_SUPERUSER,
Boolean.toString(false))
.param(
DeleteEppResourceAction.PARAM_RESOURCE_KEY,
Key.create(deletedHost).getString()));
assertAboutHosts().that(deletedHost)
.hasOnlyOneHistoryEntryWhich()
.hasType(HistoryEntry.Type.HOST_PENDING_DELETE);
assertNoBillingEvents();
assertNoDnsTasksEnqueued();
}
@Test
public void testFailure_neverExisted() throws Exception {
thrown.expect(
ResourceToMutateDoesNotExistException.class,
String.format("(%s)", getUniqueIdFromCommand()));
runFlow();
}
@Test
public void testFailure_existedButWasDeleted() throws Exception {
thrown.expect(
ResourceToMutateDoesNotExistException.class,
String.format("(%s)", getUniqueIdFromCommand()));
persistDeletedHost(getUniqueIdFromCommand(), clock.nowUtc());
runFlow();
}
@Test
public void testFailure_existedButWasClientDeleteProhibited() throws Exception {
doFailingStatusTest(
StatusValue.CLIENT_DELETE_PROHIBITED, ResourceStatusProhibitsOperationException.class);
}
@Test
public void testFailure_existedButWasServerDeleteProhibited() throws Exception {
doFailingStatusTest(
StatusValue.SERVER_DELETE_PROHIBITED, ResourceStatusProhibitsOperationException.class);
}
@Test
public void testFailure_existedButWasPendingDelete() throws Exception {
doFailingStatusTest(
StatusValue.PENDING_DELETE, ResourceStatusProhibitsOperationException.class);
}
@Test
public void testFailure_unauthorizedClient() throws Exception {
thrown.expect(ResourceNotOwnedException.class);
sessionMetadata.setClientId("NewRegistrar");
persistActiveHost(getUniqueIdFromCommand());
runFlow();
}
@Test
public void testSuccess_superuserUnauthorizedClient() throws Exception {
sessionMetadata.setSuperuser(true);
sessionMetadata.setClientId("NewRegistrar");
persistActiveHost(getUniqueIdFromCommand());
clock.advanceOneMilli();
runFlowAssertResponse(
CommitMode.LIVE, UserPrivileges.SUPERUSER, readFile("host_delete_response.xml"));
HostResource deletedHost = reloadResourceByUniqueId();
assertAboutHosts().that(deletedHost).hasStatusValue(StatusValue.PENDING_DELETE);
assertTasksEnqueued(ASYNC_FLOW_QUEUE_NAME, new TaskMatcher()
.url(getPathForAction(DeleteHostResourceAction.class))
.etaDelta(Duration.standardSeconds(75), Duration.standardSeconds(105)) // expected: 90
.param(
DeleteEppResourceAction.PARAM_REQUESTING_CLIENT_ID,
"NewRegistrar")
.param(
DeleteEppResourceAction.PARAM_IS_SUPERUSER,
Boolean.toString(true))
.param(
DeleteEppResourceAction.PARAM_RESOURCE_KEY,
Key.create(deletedHost).getString()));
assertAboutHosts().that(deletedHost)
.hasOnlyOneHistoryEntryWhich()
.hasType(HistoryEntry.Type.HOST_PENDING_DELETE);
assertNoBillingEvents();
assertNoDnsTasksEnqueued();
}
@Test
public void testFailure_failfastWhenLinkedToDomain() throws Exception {
createTld("tld");
persistResource(newDomainResource("example.tld").asBuilder()
.setNameservers(ImmutableSet.of(
ReferenceUnion.create(persistActiveHost(getUniqueIdFromCommand()))))
.build());
thrown.expect(ResourceToDeleteIsReferencedException.class);
runFlow();
}
@Test
public void testFailure_failfastWhenLinkedToApplication() throws Exception {
createTld("tld");
persistResource(newDomainApplication("example.tld").asBuilder()
.setNameservers(ImmutableSet.of(
ReferenceUnion.create(persistActiveHost(getUniqueIdFromCommand()))))
.build());
thrown.expect(ResourceToDeleteIsReferencedException.class);
runFlow();
}
}

View file

@ -0,0 +1,170 @@
// 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 com.google.domain.registry.flows.host;
import static com.google.common.truth.Truth.assertThat;
import static com.google.domain.registry.model.EppResourceUtils.isDeleted;
import static com.google.domain.registry.testing.DatastoreHelper.assertNoBillingEvents;
import static com.google.domain.registry.testing.DatastoreHelper.createTld;
import static com.google.domain.registry.testing.DatastoreHelper.newDomainResource;
import static com.google.domain.registry.testing.DatastoreHelper.persistResource;
import com.google.common.collect.ImmutableSet;
import com.google.common.net.InetAddresses;
import com.google.domain.registry.flows.ResourceFlowTestCase;
import com.google.domain.registry.flows.ResourceQueryFlow.ResourceToQueryDoesNotExistException;
import com.google.domain.registry.model.domain.DomainResource;
import com.google.domain.registry.model.domain.ReferenceUnion;
import com.google.domain.registry.model.eppcommon.StatusValue;
import com.google.domain.registry.model.host.HostResource;
import com.googlecode.objectify.Ref;
import org.joda.time.DateTime;
import org.junit.Before;
import org.junit.Test;
import javax.annotation.Nullable;
/** Unit tests for {@link HostInfoFlow}. */
public class HostInfoFlowTest extends ResourceFlowTestCase<HostInfoFlow, HostResource> {
public HostInfoFlowTest() {
setEppInput("host_info.xml");
}
@Before
public void initHostTest() {
createTld("foobar");
}
private HostResource persistHostResource(boolean active) throws Exception {
HostResource host = persistResource(
new HostResource.Builder()
.setFullyQualifiedHostName(getUniqueIdFromCommand())
.setRepoId("1FF-FOOBAR")
.setDeletionTime(active ? null : DateTime.now().minusDays(1))
.setCurrentSponsorClientId("my sponsor")
.setStatusValues(
ImmutableSet.of(StatusValue.CLIENT_UPDATE_PROHIBITED))
.setInetAddresses(ImmutableSet.of(
InetAddresses.forString("192.0.2.2"),
InetAddresses.forString("1080:0:0:0:8:800:200C:417A"),
InetAddresses.forString("192.0.2.29")))
.setCurrentSponsorClientId("TheRegistrar")
.setCreationClientId("NewRegistrar")
.setLastEppUpdateClientId("NewRegistrar")
.setCreationTimeForTest(DateTime.parse("1999-04-03T22:00:00.0Z"))
.setLastEppUpdateTime(DateTime.parse("1999-12-03T09:00:00.0Z"))
.setLastTransferTime(DateTime.parse("2000-04-08T09:00:00.0Z"))
.build());
assertThat(isDeleted(host, DateTime.now())).isNotEqualTo(active);
return host;
}
@Test
public void testSuccess() throws Exception {
persistHostResource(true);
assertTransactionalFlow(false);
// Check that the persisted host info was returned.
runFlowAssertResponse(
readFile("host_info_response.xml"),
// We use a different roid scheme than the samples so ignore it.
"epp.response.resData.infData.roid");
assertNoHistory();
assertNoBillingEvents();
}
@Test
public void testSuccess_linked() throws Exception {
persistHostResource(true);
persistResource(
newDomainResource("example.foobar").asBuilder()
.addNameservers(
ImmutableSet.of(ReferenceUnion.<HostResource>create(persistHostResource(true))))
.build());
assertTransactionalFlow(false);
// Check that the persisted host info was returned.
runFlowAssertResponse(
readFile("host_info_response_linked.xml"),
// We use a different roid scheme than the samples so ignore it.
"epp.response.resData.infData.roid");
assertNoHistory();
assertNoBillingEvents();
}
private void runTest_superordinateDomain(DateTime domainTransferTime,
@Nullable DateTime lastSuperordinateChange) throws Exception {
DomainResource domain = persistResource(
newDomainResource("parent.foobar").asBuilder()
.setRepoId("BEEF-FOOBAR")
.setLastTransferTime(domainTransferTime)
.setCurrentSponsorClientId("superclientid")
.build());
persistResource(
persistHostResource(true).asBuilder()
.setRepoId("CEEF-FOOBAR")
.setSuperordinateDomain(Ref.create(domain))
.setLastSuperordinateChange(lastSuperordinateChange)
.build());
assertTransactionalFlow(false);
runFlowAssertResponse(
readFile("host_info_response_superordinate_clientid.xml"),
// We use a different roid scheme than the samples so ignore it.
"epp.response.resData.infData.roid");
assertNoHistory();
assertNoBillingEvents();
}
@Test
public void testSuccess_withSuperordinateDomain_hostMovedAfterDomainTransfer()
throws Exception {
runTest_superordinateDomain(DateTime.parse("2000-01-08T09:00:00.0Z"),
DateTime.parse("2000-03-01T01:00:00.0Z"));
}
@Test
public void testSuccess_withSuperordinateDomain_hostMovedBeforeDomainTransfer()
throws Exception {
runTest_superordinateDomain(DateTime.parse("2000-04-08T09:00:00.0Z"),
DateTime.parse("2000-02-08T09:00:00.0Z"));
}
@Test
public void testSuccess_withSuperordinateDomain() throws Exception {
runTest_superordinateDomain(DateTime.parse("2000-04-08T09:00:00.0Z"), null);
}
@Test
public void testFailure_neverExisted() throws Exception {
thrown.expect(
ResourceToQueryDoesNotExistException.class,
String.format("(%s)", getUniqueIdFromCommand()));
runFlow();
}
@Test
public void testFailure_existedButWasDeleted() throws Exception {
thrown.expect(
ResourceToQueryDoesNotExistException.class,
String.format("(%s)", getUniqueIdFromCommand()));
persistHostResource(false);
runFlow();
}
// Extra methods so the test runner doesn't produce empty shards.
@Test public void testNothing1() {}
}

View file

@ -0,0 +1,892 @@
// 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 com.google.domain.registry.flows.host;
import static com.google.common.truth.Truth.assertThat;
import static com.google.domain.registry.flows.async.AsyncFlowUtils.ASYNC_FLOW_QUEUE_NAME;
import static com.google.domain.registry.model.EppResourceUtils.loadByUniqueId;
import static com.google.domain.registry.request.Actions.getPathForAction;
import static com.google.domain.registry.testing.DatastoreHelper.assertNoBillingEvents;
import static com.google.domain.registry.testing.DatastoreHelper.createTld;
import static com.google.domain.registry.testing.DatastoreHelper.newDomainResource;
import static com.google.domain.registry.testing.DatastoreHelper.newHostResource;
import static com.google.domain.registry.testing.DatastoreHelper.persistActiveDomain;
import static com.google.domain.registry.testing.DatastoreHelper.persistActiveHost;
import static com.google.domain.registry.testing.DatastoreHelper.persistActiveSubordinateHost;
import static com.google.domain.registry.testing.DatastoreHelper.persistDeletedHost;
import static com.google.domain.registry.testing.DatastoreHelper.persistResource;
import static com.google.domain.registry.testing.GenericEppResourceSubject.assertAboutEppResources;
import static com.google.domain.registry.testing.HostResourceSubject.assertAboutHosts;
import static com.google.domain.registry.testing.TaskQueueHelper.assertDnsTasksEnqueued;
import static com.google.domain.registry.testing.TaskQueueHelper.assertNoDnsTasksEnqueued;
import static com.google.domain.registry.testing.TaskQueueHelper.assertTasksEnqueued;
import static com.google.domain.registry.util.DateTimeUtils.END_OF_TIME;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.domain.registry.flows.FlowRunner.CommitMode;
import com.google.domain.registry.flows.FlowRunner.UserPrivileges;
import com.google.domain.registry.flows.ResourceFlowTestCase;
import com.google.domain.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
import com.google.domain.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException;
import com.google.domain.registry.flows.ResourceUpdateFlow.ResourceHasClientUpdateProhibitedException;
import com.google.domain.registry.flows.ResourceUpdateFlow.StatusNotClientSettableException;
import com.google.domain.registry.flows.SingleResourceFlow.ResourceStatusProhibitsOperationException;
import com.google.domain.registry.flows.async.DnsRefreshForHostRenameAction;
import com.google.domain.registry.flows.host.HostFlowUtils.HostNameTooShallowException;
import com.google.domain.registry.flows.host.HostFlowUtils.InvalidHostNameException;
import com.google.domain.registry.flows.host.HostFlowUtils.SuperordinateDomainDoesNotExistException;
import com.google.domain.registry.flows.host.HostUpdateFlow.CannotAddIpToExternalHostException;
import com.google.domain.registry.flows.host.HostUpdateFlow.CannotRemoveSubordinateHostLastIpException;
import com.google.domain.registry.flows.host.HostUpdateFlow.HostAlreadyExistsException;
import com.google.domain.registry.flows.host.HostUpdateFlow.RenameHostToExternalRemoveIpException;
import com.google.domain.registry.flows.host.HostUpdateFlow.RenameHostToSubordinateRequiresIpException;
import com.google.domain.registry.model.domain.DomainResource;
import com.google.domain.registry.model.domain.ReferenceUnion;
import com.google.domain.registry.model.eppcommon.StatusValue;
import com.google.domain.registry.model.host.HostResource;
import com.google.domain.registry.model.index.ForeignKeyIndex;
import com.google.domain.registry.model.reporting.HistoryEntry;
import com.google.domain.registry.testing.TaskQueueHelper.TaskMatcher;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Ref;
import org.joda.time.DateTime;
import org.junit.Before;
import org.junit.Test;
import java.net.InetAddress;
import javax.annotation.Nullable;
/** Unit tests for {@link HostUpdateFlow}. */
public class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, HostResource> {
private void setEppHostUpdateInput(
String oldHostName, String newHostName, String addHostAddrs, String remHostAddrs) {
setEppInput(
"host_update.xml",
ImmutableMap.of(
"OLD-HOSTNAME", oldHostName,
"NEW-HOSTNAME", newHostName,
"ADD-HOSTADDRS", (addHostAddrs == null) ? "" : addHostAddrs,
"REM-HOSTADDRS", (remHostAddrs == null) ? "" : remHostAddrs));
}
public HostUpdateFlowTest() {
setEppHostUpdateInput("ns1.example.tld", "ns2.example.tld", null, null);
}
@Before
public void initHostTest() throws Exception {
createTld("xn--q9jyb4c");
}
/** Alias for better readability. */
private String oldHostName() throws Exception {
return getUniqueIdFromCommand();
}
@Test
public void testDryRun() throws Exception {
persistActiveHost("ns1.example.tld");
dryRunFlowAssertResponse(readFile("host_update_response.xml"));
}
private HostResource doSuccessfulTest() throws Exception {
clock.advanceOneMilli();
assertTransactionalFlow(true);
runFlowAssertResponse(readFile("host_update_response.xml"));
// The example xml does a host rename, so reloading the host (which uses the original host name)
// should now return null.
assertThat(reloadResourceByUniqueId()).isNull();
// However, it should load correctly if we use the new name (taken from the xml).
HostResource renamedHost =
loadByUniqueId(HostResource.class, "ns2.example.tld", clock.nowUtc());
assertAboutHosts().that(renamedHost)
.hasOnlyOneHistoryEntryWhich()
.hasType(HistoryEntry.Type.HOST_UPDATE);
assertNoBillingEvents();
return renamedHost;
}
@Test
public void testSuccess_removeClientUpdateProhibited() throws Exception {
setEppInput("host_update_remove_client_update_prohibited.xml");
persistActiveHost(oldHostName());
persistResource(
newHostResource(oldHostName()).asBuilder()
.setStatusValues(ImmutableSet.of(StatusValue.CLIENT_UPDATE_PROHIBITED))
.build());
clock.advanceOneMilli();
runFlow();
assertAboutEppResources().that(reloadResourceByUniqueId())
.doesNotHaveStatusValue(StatusValue.CLIENT_UPDATE_PROHIBITED);
}
@Test
public void testSuccess_rename_noOtherHostEverUsedTheOldName() throws Exception {
persistActiveHost(oldHostName());
HostResource renamedHost = doSuccessfulTest();
assertThat(renamedHost.getSuperordinateDomain()).isNull();
assertNoDnsTasksEnqueued(); // No tasks enqueued since it's a rename of an external host.
// The old ForeignKeyIndex is invalidated at the time we did the rename.
ForeignKeyIndex<HostResource> oldFkiBeforeRename =
ForeignKeyIndex.load(
HostResource.class, oldHostName(), clock.nowUtc().minusMillis(1));
assertThat(oldFkiBeforeRename.getReference()).isEqualTo(Ref.create(renamedHost));
assertThat(oldFkiBeforeRename.getDeletionTime()).isEqualTo(clock.nowUtc());
ForeignKeyIndex<HostResource> oldFkiAfterRename =
ForeignKeyIndex.load(
HostResource.class, oldHostName(), clock.nowUtc());
assertThat(oldFkiAfterRename).isNull();
}
@Test
public void testSuccess_withReferencingDomain() throws Exception {
HostResource host = persistActiveHost(oldHostName());
persistResource(
newDomainResource("test.xn--q9jyb4c").asBuilder()
.setDeletionTime(END_OF_TIME)
.setNameservers(ImmutableSet.of(ReferenceUnion.create(host)))
.build());
HostResource renamedHost = doSuccessfulTest();
assertThat(renamedHost.getSuperordinateDomain()).isNull();
// Task enqueued to change the NS record of the referencing domain via mapreduce.
assertTasksEnqueued(ASYNC_FLOW_QUEUE_NAME, new TaskMatcher()
.url(getPathForAction(DnsRefreshForHostRenameAction.class))
.param(DnsRefreshForHostRenameAction.PARAM_HOST_KEY, Key.create(renamedHost).getString()));
}
@Test
public void testSuccess_nameUnchanged() throws Exception {
setEppInput("host_update_name_unchanged.xml");
createTld("tld");
DomainResource domain = persistActiveDomain("example.tld");
persistActiveSubordinateHost(oldHostName(), domain);
clock.advanceOneMilli();
runFlowAssertResponse(readFile("host_update_response.xml"));
// The example xml doesn't do a host rename, so reloading the host should work.
assertAboutHosts().that(reloadResourceByUniqueId())
.hasOnlyOneHistoryEntryWhich()
.hasType(HistoryEntry.Type.HOST_UPDATE);
assertDnsTasksEnqueued("ns1.example.tld");
}
@Test
public void testSuccess_renameWithSameSuperordinateDomain() throws Exception {
setEppHostUpdateInput(
"ns1.example.tld",
"ns2.example.tld",
"<host:addr ip=\"v4\">192.0.2.22</host:addr>",
"<host:addr ip=\"v6\">1080:0:0:0:8:800:200C:417A</host:addr>");
createTld("tld");
DomainResource domain = persistActiveDomain("example.tld");
persistActiveSubordinateHost(oldHostName(), domain);
persistResource(
domain.asBuilder()
.setSubordinateHosts(ImmutableSet.of(oldHostName()))
.build());
assertThat(
loadByUniqueId(
DomainResource.class, "example.tld", clock.nowUtc()).getSubordinateHosts())
.containsExactly("ns1.example.tld");
HostResource renamedHost = doSuccessfulTest();
assertThat(renamedHost.getSuperordinateDomain()).isEqualTo(Ref.create(domain));
assertThat(
loadByUniqueId(
DomainResource.class, "example.tld", clock.nowUtc()).getSubordinateHosts())
.containsExactly("ns2.example.tld");
assertDnsTasksEnqueued("ns1.example.tld", "ns2.example.tld");
}
@Test
public void testSuccess_internalToSameInternal() throws Exception {
setEppHostUpdateInput(
"ns2.foo.tld",
"ns2.example.tld",
"<host:addr ip=\"v4\">192.0.2.22</host:addr>",
"<host:addr ip=\"v6\">1080:0:0:0:8:800:200C:417A</host:addr>");
createTld("tld");
DomainResource foo = persistActiveDomain("foo.tld");
DomainResource example = persistActiveDomain("example.tld");
persistActiveSubordinateHost(oldHostName(), foo);
persistResource(
foo.asBuilder()
.setSubordinateHosts(ImmutableSet.of(oldHostName()))
.build());
assertThat(
loadByUniqueId(
DomainResource.class, "foo.tld", clock.nowUtc()).getSubordinateHosts())
.containsExactly("ns2.foo.tld");
assertThat(
loadByUniqueId(
DomainResource.class, "example.tld", clock.nowUtc()).getSubordinateHosts())
.isEmpty();
HostResource renamedHost = doSuccessfulTest();
assertThat(renamedHost.getSuperordinateDomain()).isEqualTo(Ref.create(example));
assertThat(
loadByUniqueId(
DomainResource.class, "foo.tld", clock.nowUtc()).getSubordinateHosts())
.isEmpty();
assertThat(
loadByUniqueId(
DomainResource.class, "example.tld", clock.nowUtc()).getSubordinateHosts())
.containsExactly("ns2.example.tld");
assertDnsTasksEnqueued("ns2.foo.tld", "ns2.example.tld");
}
@Test
public void testSuccess_internalToExternal() throws Exception {
setEppHostUpdateInput(
"ns1.example.foo",
"ns2.example.tld",
null,
"<host:addr ip=\"v6\">1080:0:0:0:8:800:200C:417A</host:addr>");
createTld("foo");
DomainResource domain = persistActiveDomain("example.foo");
persistActiveSubordinateHost(oldHostName(), domain);
persistResource(
domain.asBuilder()
.setSubordinateHosts(ImmutableSet.of(oldHostName()))
.build());
assertThat(
loadByUniqueId(
DomainResource.class, "example.foo", clock.nowUtc()).getSubordinateHosts())
.containsExactly("ns1.example.foo");
HostResource renamedHost = doSuccessfulTest();
assertThat(renamedHost.getSuperordinateDomain()).isNull();
// Ensure that the client id is set to the new registrar correctly (and that this necessarily
// comes from the field on the host itself, because the superordinate domain is null).
assertThat(renamedHost.getCurrentSponsorClientId()).isEqualTo("TheRegistrar");
assertThat(
loadByUniqueId(
DomainResource.class, "example.foo", clock.nowUtc()).getSubordinateHosts())
.isEmpty();
assertDnsTasksEnqueued("ns1.example.foo");
}
@Test
public void testSuccess_internalToDifferentInternal() throws Exception {
setEppHostUpdateInput(
"ns1.example.foo",
"ns2.example.tld",
"<host:addr ip=\"v4\">192.0.2.22</host:addr>",
"<host:addr ip=\"v6\">1080:0:0:0:8:800:200C:417A</host:addr>");
createTld("foo");
persistActiveDomain("example.foo");
createTld("tld");
DomainResource tldDomain = persistActiveDomain("example.tld");
persistActiveHost(oldHostName());
assertThat(loadByUniqueId(
HostResource.class, oldHostName(), clock.nowUtc()).getCurrentSponsorClientId())
.isEqualTo("TheRegistrar");
assertThat(
loadByUniqueId(
DomainResource.class, "example.tld", clock.nowUtc()).getSubordinateHosts())
.isEmpty();
HostResource renamedHost = doSuccessfulTest();
assertThat(renamedHost.getSuperordinateDomain()).isEqualTo(Ref.create(tldDomain));
assertThat(loadByUniqueId(
DomainResource.class, "example.tld", clock.nowUtc()).getSubordinateHosts())
.containsExactly("ns2.example.tld");
assertDnsTasksEnqueued("ns2.example.tld");
// Ensure that the client id is read off the domain because this is a subordinate host now.
persistResource(
tldDomain.asBuilder().setCurrentSponsorClientId("it_should_be_this").build());
assertThat(
renamedHost.cloneProjectedAtTime(clock.nowUtc().plusMinutes(1)).getCurrentSponsorClientId())
.isEqualTo("it_should_be_this");
}
@Test
public void testSuccess_externalToInternal() throws Exception {
setEppHostUpdateInput(
"ns1.example.foo",
"ns2.example.tld",
"<host:addr ip=\"v4\">192.0.2.22</host:addr>",
null);
createTld("tld");
DomainResource domain = persistActiveDomain("example.tld");
persistActiveHost(oldHostName());
assertThat(loadByUniqueId(
HostResource.class, oldHostName(), clock.nowUtc()).getCurrentSponsorClientId())
.isEqualTo("TheRegistrar");
assertThat(loadByUniqueId(
DomainResource.class, "example.tld", clock.nowUtc()).getSubordinateHosts())
.isEmpty();
HostResource renamedHost = doSuccessfulTest();
assertThat(renamedHost.getSuperordinateDomain()).isEqualTo(Ref.create(domain));
assertThat(loadByUniqueId(
DomainResource.class, "example.tld", clock.nowUtc()).getSubordinateHosts())
.containsExactly("ns2.example.tld");
assertDnsTasksEnqueued("ns2.example.tld");
// Ensure that the client id is read off the domain because this is a subordinate host now.
persistResource(
domain.asBuilder().setCurrentSponsorClientId("it_should_be_this").build());
assertThat(
renamedHost.cloneProjectedAtTime(clock.nowUtc().plusMinutes(1)).getCurrentSponsorClientId())
.isEqualTo("it_should_be_this");
}
@Test
public void testSuccess_superuserClientUpdateProhibited() throws Exception {
setEppInput("host_update_add_status.xml");
persistResource(
newHostResource(oldHostName()).asBuilder()
.setStatusValues(ImmutableSet.of(StatusValue.CLIENT_UPDATE_PROHIBITED))
.build());
clock.advanceOneMilli();
runFlowAssertResponse(
CommitMode.LIVE,
UserPrivileges.SUPERUSER,
readFile("host_update_response.xml"));
assertAboutHosts().that(reloadResourceByUniqueId())
.hasStatusValue(StatusValue.CLIENT_UPDATE_PROHIBITED).and()
.hasStatusValue(StatusValue.SERVER_UPDATE_PROHIBITED);
}
@Test
public void testSuccess_subordToSubord_lastTransferTimeFromPreviousSuperordinateWinsOut()
throws Exception {
setEppHostUpdateInput(
"ns2.foo.tld",
"ns2.example.tld",
"<host:addr ip=\"v4\">192.0.2.22</host:addr>",
"<host:addr ip=\"v6\">1080:0:0:0:8:800:200C:417A</host:addr>");
createTld("tld");
DateTime lastTransferTime = clock.nowUtc().minusDays(5);
DomainResource foo = newDomainResource("foo.tld").asBuilder()
.setLastTransferTime(lastTransferTime)
.build();
// Set the new domain to have a last transfer time that is different than the last transfer
// time on the host in question.
persistResource(
newDomainResource("example.tld").asBuilder()
.setLastTransferTime(clock.nowUtc().minusDays(10))
.build());
persistResource(
newHostResource(oldHostName()).asBuilder()
.setSuperordinateDomain(Ref.create(foo))
.setLastTransferTime(null)
.build());
persistResource(
foo.asBuilder()
.setSubordinateHosts(ImmutableSet.of(oldHostName()))
.build());
clock.advanceOneMilli();
HostResource renamedHost = doSuccessfulTest();
assertThat(renamedHost.getLastTransferTime()).isEqualTo(lastTransferTime);
}
@Test
public void testSuccess_subordToSubord_lastTransferTimeOnExistingHostWinsOut()
throws Exception {
setEppHostUpdateInput(
"ns2.foo.tld",
"ns2.example.tld",
"<host:addr ip=\"v4\">192.0.2.22</host:addr>",
"<host:addr ip=\"v6\">1080:0:0:0:8:800:200C:417A</host:addr>");
createTld("tld");
DomainResource domain = newDomainResource("foo.tld").asBuilder()
.setLastTransferTime(clock.nowUtc().minusDays(5))
.build();
// Set the new domain to have a last transfer time that is different than the last transfer
// time on the host in question.
persistResource(
newDomainResource("example.tld").asBuilder()
.setLastTransferTime(clock.nowUtc().minusDays(10))
.build());
HostResource host = persistResource(
newHostResource(oldHostName()).asBuilder()
.setSuperordinateDomain(Ref.create(domain))
.setLastTransferTime(clock.nowUtc().minusDays(20))
.setLastSuperordinateChange(clock.nowUtc().minusDays(3))
.build());
DateTime lastTransferTime = host.getLastTransferTime();
persistResource(
domain.asBuilder().setSubordinateHosts(ImmutableSet.of(oldHostName())).build());
HostResource renamedHost = doSuccessfulTest();
assertThat(renamedHost.getLastTransferTime()).isEqualTo(lastTransferTime);
}
@Test
public void testSuccess_subordToSubord_lastTransferTimeOnExistingHostWinsOut_whenNullOnNewDomain()
throws Exception {
setEppHostUpdateInput(
"ns2.foo.tld",
"ns2.example.tld",
"<host:addr ip=\"v4\">192.0.2.22</host:addr>",
"<host:addr ip=\"v6\">1080:0:0:0:8:800:200C:417A</host:addr>");
createTld("tld");
DomainResource foo = newDomainResource("foo.tld").asBuilder()
.setLastTransferTime(clock.nowUtc().minusDays(5))
.build();
// Set the new domain to have a null last transfer time.
persistResource(
newDomainResource("example.tld").asBuilder().setLastTransferTime(null).build());
DateTime lastTransferTime = clock.nowUtc().minusDays(20);
persistResource(
newHostResource(oldHostName()).asBuilder()
.setSuperordinateDomain(Ref.create(foo))
.setLastTransferTime(lastTransferTime)
.setLastSuperordinateChange(clock.nowUtc().minusDays(3))
.build());
persistResource(
foo.asBuilder()
.setSubordinateHosts(ImmutableSet.of(oldHostName()))
.build());
clock.advanceOneMilli();
HostResource renamedHost = doSuccessfulTest();
assertThat(renamedHost.getLastTransferTime()).isEqualTo(lastTransferTime);
}
@Test
public void testSuccess_subordToSubord_lastTransferTimeOnExistingHostWins_whenNullOnBothDomains()
throws Exception {
setEppHostUpdateInput(
"ns2.foo.tld",
"ns2.example.tld",
"<host:addr ip=\"v4\">192.0.2.22</host:addr>",
"<host:addr ip=\"v6\">1080:0:0:0:8:800:200C:417A</host:addr>");
createTld("tld");
DomainResource foo = newDomainResource("foo.tld").asBuilder()
.setLastTransferTime(null)
.build();
// Set the new domain to have a null last transfer time.
persistResource(
newDomainResource("example.tld").asBuilder()
.setLastTransferTime(null)
.build());
DateTime lastTransferTime = clock.nowUtc().minusDays(20);
persistResource(
newHostResource(oldHostName()).asBuilder()
.setSuperordinateDomain(Ref.create(foo))
.setLastTransferTime(lastTransferTime)
.setLastSuperordinateChange(clock.nowUtc().minusDays(10))
.build());
persistResource(
foo.asBuilder()
.setSubordinateHosts(ImmutableSet.of(oldHostName()))
.build());
clock.advanceOneMilli();
HostResource renamedHost = doSuccessfulTest();
assertThat(renamedHost.getLastTransferTime()).isEqualTo(lastTransferTime);
}
@Test
public void testSuccess_subordToSubord_lastTransferTimeIsNull_whenNullOnBoth()
throws Exception {
setEppHostUpdateInput(
"ns2.foo.tld",
"ns2.example.tld",
"<host:addr ip=\"v4\">192.0.2.22</host:addr>",
"<host:addr ip=\"v6\">1080:0:0:0:8:800:200C:417A</host:addr>");
createTld("tld");
DomainResource foo = newDomainResource("foo.tld").asBuilder()
.setLastTransferTime(clock.nowUtc().minusDays(5))
.build();
// Set the new domain to have a null last transfer time.
persistResource(
newDomainResource("example.tld").asBuilder()
.setLastTransferTime(null)
.build());
persistResource(
newHostResource(oldHostName()).asBuilder()
.setSuperordinateDomain(Ref.create(foo))
.setLastTransferTime(null)
.setLastSuperordinateChange(clock.nowUtc().minusDays(3))
.build());
persistResource(
foo.asBuilder().setSubordinateHosts(ImmutableSet.of(oldHostName())).build());
HostResource renamedHost = doSuccessfulTest();
assertThat(renamedHost.getLastTransferTime()).isNull();
}
@Test
public void testSuccess_internalToExternal_lastTransferTimeFrozenWhenComingFromSuperordinate()
throws Exception {
setEppHostUpdateInput(
"ns1.example.foo",
"ns2.example.tld",
null,
"<host:addr ip=\"v6\">1080:0:0:0:8:800:200C:417A</host:addr>");
createTld("foo");
DomainResource domain = persistActiveDomain("example.foo");
persistResource(
newHostResource(oldHostName()).asBuilder()
.setSuperordinateDomain(Ref.create(domain))
.build());
DateTime lastTransferTime = clock.nowUtc().minusDays(2);
persistResource(
domain.asBuilder()
.setLastTransferTime(lastTransferTime)
.setSubordinateHosts(ImmutableSet.of(oldHostName()))
.build());
clock.advanceOneMilli();
HostResource renamedHost = doSuccessfulTest();
persistResource(
domain.asBuilder()
.setLastTransferTime(clock.nowUtc().minusDays(1))
.build());
// The last transfer time should be what was on the superordinate domain at the time of the host
// update, not what it is later changed to.
assertThat(renamedHost.getLastTransferTime()).isEqualTo(lastTransferTime);
}
@Test
public void testSuccess_internalToExternal_lastTransferTimeFrozenWhenComingFromHost()
throws Exception {
setEppHostUpdateInput(
"ns1.example.foo",
"ns2.example.tld",
null,
"<host:addr ip=\"v6\">1080:0:0:0:8:800:200C:417A</host:addr>");
createTld("foo");
DomainResource domain = persistActiveDomain("example.foo");
DateTime lastTransferTime = clock.nowUtc().minusDays(12);
persistResource(
newHostResource(oldHostName()).asBuilder()
.setSuperordinateDomain(Ref.create(domain))
.setLastTransferTime(lastTransferTime)
.setLastSuperordinateChange(clock.nowUtc().minusDays(4))
.build());
persistResource(
domain.asBuilder()
.setLastTransferTime(clock.nowUtc().minusDays(14))
.setSubordinateHosts(ImmutableSet.of(oldHostName()))
.build());
clock.advanceOneMilli();
HostResource renamedHost = doSuccessfulTest();
// The last transfer time should be what was on the host, because the host's old superordinate
// domain wasn't transferred more recently than when the host was changed to have that
// superordinate domain.
assertThat(renamedHost.getLastTransferTime()).isEqualTo(lastTransferTime);
}
@Test
public void testSuccess_internalToExternal_lastTransferTimeFrozenWhenDomainOverridesHost()
throws Exception {
setEppHostUpdateInput(
"ns1.example.foo",
"ns2.example.tld",
null,
"<host:addr ip=\"v6\">1080:0:0:0:8:800:200C:417A</host:addr>");
createTld("foo");
DomainResource domain = persistActiveDomain("example.foo");
persistResource(
newHostResource(oldHostName()).asBuilder()
.setSuperordinateDomain(Ref.create(domain))
.setLastTransferTime(clock.nowUtc().minusDays(12))
.setLastSuperordinateChange(clock.nowUtc().minusDays(4))
.build());
domain = persistResource(
domain.asBuilder()
.setLastTransferTime(clock.nowUtc().minusDays(2))
.setSubordinateHosts(ImmutableSet.of(oldHostName()))
.build());
HostResource renamedHost = doSuccessfulTest();
// The last transfer time should be what was on the superordinate domain, because the domain
// was transferred more recently than the last time the host's superordinate domain was changed.
assertThat(renamedHost.getLastTransferTime()).isEqualTo(domain.getLastTransferTime());
}
private void doExternalToInternalLastTransferTimeTest(
DateTime hostTransferTime, @Nullable DateTime domainTransferTime) throws Exception {
setEppHostUpdateInput(
"ns1.example.foo",
"ns2.example.tld",
"<host:addr ip=\"v4\">192.0.2.22</host:addr>",
null);
createTld("tld");
persistResource(
newDomainResource("example.tld").asBuilder()
.setLastTransferTime(domainTransferTime)
.build());
persistResource(
newHostResource(oldHostName()).asBuilder()
.setLastTransferTime(hostTransferTime)
.build());
HostResource renamedHost = doSuccessfulTest();
assertThat(renamedHost.getLastTransferTime()).isEqualTo(hostTransferTime);
}
@Test
public void testSuccess_externalToSubord_lastTransferTimeNotOverridden_whenLessRecent()
throws Exception {
doExternalToInternalLastTransferTimeTest(
clock.nowUtc().minusDays(2), clock.nowUtc().minusDays(1));
}
@Test
public void testSuccess_externalToSubord_lastTransferTimeNotOverridden_whenMoreRecent()
throws Exception {
doExternalToInternalLastTransferTimeTest(
clock.nowUtc().minusDays(2), clock.nowUtc().minusDays(3));
}
/** Test when the new superdordinate domain has never been transferred before. */
@Test
public void testSuccess_externalToSubord_lastTransferTimeNotOverridden_whenNull()
throws Exception {
doExternalToInternalLastTransferTimeTest(clock.nowUtc().minusDays(2), null);
}
@Test
public void testFailure_superordinateMissing() throws Exception {
createTld("tld");
persistActiveHost(oldHostName());
thrown.expect(
SuperordinateDomainDoesNotExistException.class,
"(example.tld)");
runFlow();
}
@Test
public void testFailure_neverExisted() throws Exception {
thrown.expect(
ResourceToMutateDoesNotExistException.class,
String.format("(%s)", getUniqueIdFromCommand()));
runFlow();
}
@Test
public void testFailure_neverExisted_updateWithoutNameChange() throws Exception {
setEppInput("host_update_name_unchanged.xml");
thrown.expect(
ResourceToMutateDoesNotExistException.class,
String.format("(%s)", getUniqueIdFromCommand()));
runFlow();
}
@Test
public void testFailure_existedButWasDeleted() throws Exception {
persistDeletedHost(oldHostName(), clock.nowUtc());
thrown.expect(
ResourceToMutateDoesNotExistException.class,
String.format("(%s)", getUniqueIdFromCommand()));
runFlow();
}
@Test
public void testFailure_renameToCurrentName() throws Exception {
persistActiveHost(oldHostName());
clock.advanceOneMilli();
setEppHostUpdateInput("ns1.example.tld", "ns1.example.tld", null, null);
thrown.expect(HostAlreadyExistsException.class, "ns1.example.tld");
runFlow();
}
@Test
public void testFailure_renameToNameOfExistingOtherHost() throws Exception {
persistActiveHost(oldHostName());
persistActiveHost("ns2.example.tld");
thrown.expect(HostAlreadyExistsException.class, "ns2.example.tld");
runFlow();
}
@Test
public void testFailure_clientUpdateProhibited() throws Exception {
persistResource(
newHostResource(oldHostName()).asBuilder()
.setStatusValues(ImmutableSet.of(StatusValue.CLIENT_UPDATE_PROHIBITED))
.build());
thrown.expect(ResourceHasClientUpdateProhibitedException.class);
runFlow();
}
@Test
public void testFailure_serverUpdateProhibited() throws Exception {
persistResource(
newHostResource(oldHostName()).asBuilder()
.setStatusValues(ImmutableSet.of(StatusValue.SERVER_UPDATE_PROHIBITED))
.build());
thrown.expect(ResourceStatusProhibitsOperationException.class);
runFlow();
}
@Test
public void testFailure_subordinateNeedsIps() throws Exception {
setEppHostUpdateInput(
"ns1.example.tld",
"ns2.example.tld",
null,
"<host:addr ip=\"v6\">1080:0:0:0:8:800:200C:417A</host:addr>");
createTld("tld");
persistResource(newHostResource(oldHostName()).asBuilder()
.setSuperordinateDomain(Ref.create(persistActiveDomain("example.tld")))
.build());
thrown.expect(CannotRemoveSubordinateHostLastIpException.class);
runFlow();
}
@Test
public void testFailure_externalMustNotHaveIps() throws Exception {
setEppHostUpdateInput(
"ns1.example.tld",
"ns2.example.tld",
"<host:addr ip=\"v4\">192.0.2.22</host:addr>",
"<host:addr ip=\"v6\">1080:0:0:0:8:800:200C:417A</host:addr>");
persistActiveHost(oldHostName());
thrown.expect(CannotAddIpToExternalHostException.class);
runFlow();
}
@Test
public void testFailure_subordinateToExternal_mustRemoveAllIps() throws Exception {
setEppHostUpdateInput(
"ns1.example.tld",
"ns2.example.com",
null,
null);
createTld("tld");
persistResource(newHostResource(oldHostName()).asBuilder()
.setSuperordinateDomain(Ref.create(persistActiveDomain("example.tld")))
.setInetAddresses(ImmutableSet.of(InetAddress.getLocalHost()))
.build());
thrown.expect(RenameHostToExternalRemoveIpException.class);
runFlow();
}
@Test
public void testFailure_subordinateToExternal_cantAddAnIp() throws Exception {
setEppHostUpdateInput(
"ns1.example.tld",
"ns2.example.com",
"<host:addr ip=\"v4\">192.0.2.22</host:addr>",
null);
createTld("tld");
persistResource(newHostResource(oldHostName()).asBuilder()
.setSuperordinateDomain(Ref.create(persistActiveDomain("example.tld")))
.build());
thrown.expect(CannotAddIpToExternalHostException.class);
runFlow();
}
@Test
public void testFailure_externalToSubordinate_mustAddAnIp() throws Exception {
setEppHostUpdateInput(
"ns1.example.com",
"ns2.example.tld",
null,
null);
createTld("tld");
persistActiveDomain("example.tld");
persistActiveHost(oldHostName());
clock.advanceOneMilli();
thrown.expect(RenameHostToSubordinateRequiresIpException.class);
runFlow();
}
@Test
public void testFailure_clientProhibitedStatusValue() throws Exception {
createTld("tld");
persistActiveDomain("example.tld");
setEppInput("host_update_prohibited_status.xml");
persistActiveHost(oldHostName());
thrown.expect(StatusNotClientSettableException.class);
runFlow();
}
@Test
public void testSuccess_superuserClientProhibitedStatusValue() throws Exception {
setEppInput("host_update_prohibited_status.xml");
createTld("tld");
persistActiveDomain("example.tld");
persistActiveHost(oldHostName());
clock.advanceOneMilli();
runFlowAssertResponse(
CommitMode.LIVE,
UserPrivileges.SUPERUSER,
readFile("host_update_response.xml"));
}
@Test
public void testFailure_unauthorizedClient() throws Exception {
sessionMetadata.setClientId("NewRegistrar");
persistActiveHost(oldHostName());
thrown.expect(ResourceNotOwnedException.class);
runFlow();
}
@Test
public void testSuccess_superuserUnauthorizedClient() throws Exception {
sessionMetadata.setSuperuser(true);
sessionMetadata.setClientId("NewRegistrar");
persistActiveHost(oldHostName());
clock.advanceOneMilli();
runFlowAssertResponse(
CommitMode.DRY_RUN, UserPrivileges.SUPERUSER, readFile("host_update_response.xml"));
}
private void doFailingHostNameTest(
String hostName,
Class<? extends Throwable> exception) throws Exception {
persistActiveHost(oldHostName());
setEppHostUpdateInput(
"ns1.example.tld",
hostName,
"<host:addr ip=\"v4\">192.0.2.22</host:addr>",
"<host:addr ip=\"v6\">1080:0:0:0:8:800:200C:417A</host:addr>");
thrown.expect(exception);
runFlow();
}
@Test
public void testFailure_renameToBadCharacter() throws Exception {
doFailingHostNameTest("foo bar", InvalidHostNameException.class);
}
@Test
public void testFailure_renameToTooShallowPublicSuffix() throws Exception {
doFailingHostNameTest("example.com", HostNameTooShallowException.class);
}
@Test
public void testFailure_renameToTooShallowCcTld() throws Exception {
doFailingHostNameTest("foo.co.uk", HostNameTooShallowException.class);
}
@Test
public void testFailure_renameToBarePublicSuffix() throws Exception {
doFailingHostNameTest("com", HostNameTooShallowException.class);
}
@Test
public void testFailure_renameToBareCcTld() throws Exception {
doFailingHostNameTest("co.uk", HostNameTooShallowException.class);
}
@Test
public void testFailure_renameToTooShallowNewTld() throws Exception {
doFailingHostNameTest("example.lol", HostNameTooShallowException.class);
}
@Test
public void testFailure_ccTldInBailiwick() throws Exception {
createTld("co.uk");
doFailingHostNameTest("foo.co.uk", HostNameTooShallowException.class);
}
}

View file

@ -0,0 +1,13 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<check>
<host:check
xmlns:host="urn:ietf:params:xml:ns:host-1.0">
<host:name>ns1.example.tld</host:name>
<host:name>ns2.example.tld</host:name>
<host:name>ns3.example.tld</host:name>
</host:check>
</check>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View file

@ -0,0 +1,60 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<check>
<host:check
xmlns:host="urn:ietf:params:xml:ns:host-1.0">
<host:name>www1.tld</host:name>
<host:name>www2.tld</host:name>
<host:name>www3.tld</host:name>
<host:name>www4.tld</host:name>
<host:name>www5.tld</host:name>
<host:name>www6.tld</host:name>
<host:name>www7.tld</host:name>
<host:name>www8.tld</host:name>
<host:name>www9.tld</host:name>
<host:name>www10.tld</host:name>
<host:name>www11.tld</host:name>
<host:name>www12.tld</host:name>
<host:name>www13.tld</host:name>
<host:name>www14.tld</host:name>
<host:name>www15.tld</host:name>
<host:name>www16.tld</host:name>
<host:name>www17.tld</host:name>
<host:name>www18.tld</host:name>
<host:name>www19.tld</host:name>
<host:name>www20.tld</host:name>
<host:name>www21.tld</host:name>
<host:name>www22.tld</host:name>
<host:name>www23.tld</host:name>
<host:name>www24.tld</host:name>
<host:name>www25.tld</host:name>
<host:name>www26.tld</host:name>
<host:name>www27.tld</host:name>
<host:name>www28.tld</host:name>
<host:name>www29.tld</host:name>
<host:name>www30.tld</host:name>
<host:name>www31.tld</host:name>
<host:name>www32.tld</host:name>
<host:name>www33.tld</host:name>
<host:name>www34.tld</host:name>
<host:name>www35.tld</host:name>
<host:name>www36.tld</host:name>
<host:name>www37.tld</host:name>
<host:name>www38.tld</host:name>
<host:name>www39.tld</host:name>
<host:name>www40.tld</host:name>
<host:name>www41.tld</host:name>
<host:name>www42.tld</host:name>
<host:name>www43.tld</host:name>
<host:name>www44.tld</host:name>
<host:name>www45.tld</host:name>
<host:name>www46.tld</host:name>
<host:name>www47.tld</host:name>
<host:name>www48.tld</host:name>
<host:name>www49.tld</host:name>
<host:name>www50.tld</host:name>
</host:check>
</check>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View file

@ -0,0 +1,61 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<check>
<host:check
xmlns:host="urn:ietf:params:xml:ns:host-1.0">
<host:name>www1.tld</host:name>
<host:name>www2.tld</host:name>
<host:name>www3.tld</host:name>
<host:name>www4.tld</host:name>
<host:name>www5.tld</host:name>
<host:name>www6.tld</host:name>
<host:name>www7.tld</host:name>
<host:name>www8.tld</host:name>
<host:name>www9.tld</host:name>
<host:name>www10.tld</host:name>
<host:name>www11.tld</host:name>
<host:name>www12.tld</host:name>
<host:name>www13.tld</host:name>
<host:name>www14.tld</host:name>
<host:name>www15.tld</host:name>
<host:name>www16.tld</host:name>
<host:name>www17.tld</host:name>
<host:name>www18.tld</host:name>
<host:name>www19.tld</host:name>
<host:name>www20.tld</host:name>
<host:name>www21.tld</host:name>
<host:name>www22.tld</host:name>
<host:name>www23.tld</host:name>
<host:name>www24.tld</host:name>
<host:name>www25.tld</host:name>
<host:name>www26.tld</host:name>
<host:name>www27.tld</host:name>
<host:name>www28.tld</host:name>
<host:name>www29.tld</host:name>
<host:name>www30.tld</host:name>
<host:name>www31.tld</host:name>
<host:name>www32.tld</host:name>
<host:name>www33.tld</host:name>
<host:name>www34.tld</host:name>
<host:name>www35.tld</host:name>
<host:name>www36.tld</host:name>
<host:name>www37.tld</host:name>
<host:name>www38.tld</host:name>
<host:name>www39.tld</host:name>
<host:name>www40.tld</host:name>
<host:name>www41.tld</host:name>
<host:name>www42.tld</host:name>
<host:name>www43.tld</host:name>
<host:name>www44.tld</host:name>
<host:name>www45.tld</host:name>
<host:name>www46.tld</host:name>
<host:name>www47.tld</host:name>
<host:name>www48.tld</host:name>
<host:name>www49.tld</host:name>
<host:name>www50.tld</host:name>
<host:name>www51.tld</host:name>
</host:check>
</check>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View file

@ -0,0 +1,28 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<resData>
<host:chkData
xmlns:host="urn:ietf:params:xml:ns:host-1.0">
<host:cd>
<host:name avail="1">ns1.example.tld</host:name>
</host:cd>
<host:cd>
<!-- The RFC uses ns2.example2.tld here; it's clearly a typo. -->
<host:name avail="0">ns2.example.tld</host:name>
<host:reason>In use</host:reason>
</host:cd>
<host:cd>
<!-- The RFC uses ns3.example3.tld here; it's clearly a typo. -->
<host:name avail="1">ns3.example.tld</host:name>
</host:cd>
</host:chkData>
</resData>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>server-trid</svTRID>
</trID>
</response>
</epp>

View file

@ -0,0 +1,12 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<create>
<host:create
xmlns:host="urn:ietf:params:xml:ns:host-1.0">
<host:name>%HOSTNAME%</host:name>
%HOSTADDRS%
</host:create>
</create>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View file

@ -0,0 +1,18 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<resData>
<host:creData
xmlns:host="urn:ietf:params:xml:ns:host-1.0">
<host:name>ns1.example.tld</host:name>
<host:crDate>1999-04-03T22:00:00.0Z</host:crDate>
</host:creData>
</resData>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>server-trid</svTRID>
</trID>
</response>
</epp>

View file

@ -0,0 +1,11 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<delete>
<host:delete
xmlns:host="urn:ietf:params:xml:ns:host-1.0">
<host:name>ns1.example.tld</host:name>
</host:delete>
</delete>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View file

@ -0,0 +1,11 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1001">
<msg>Command completed successfully; action pending</msg>
</result>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>server-trid</svTRID>
</trID>
</response>
</epp>

View file

@ -0,0 +1,11 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<info>
<host:info
xmlns:host="urn:ietf:params:xml:ns:host-1.0">
<host:name>ns1.example.tld</host:name>
</host:info>
</info>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View file

@ -0,0 +1,28 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<resData>
<host:infData
xmlns:host="urn:ietf:params:xml:ns:host-1.0">
<host:name>ns1.example.tld</host:name>
<host:roid>NS1_EXAMPLE1-REP</host:roid>
<host:status s="clientUpdateProhibited"/>
<host:addr ip="v4">192.0.2.2</host:addr>
<host:addr ip="v4">192.0.2.29</host:addr>
<host:addr ip="v6">1080:0:0:0:8:800:200C:417A</host:addr>
<host:clID>TheRegistrar</host:clID>
<host:crID>NewRegistrar</host:crID>
<host:crDate>1999-04-03T22:00:00.0Z</host:crDate>
<host:upID>NewRegistrar</host:upID>
<host:upDate>1999-12-03T09:00:00.0Z</host:upDate>
<host:trDate>2000-04-08T09:00:00.0Z</host:trDate>
</host:infData>
</resData>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>server-trid</svTRID>
</trID>
</response>
</epp>

View file

@ -0,0 +1,29 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<resData>
<host:infData
xmlns:host="urn:ietf:params:xml:ns:host-1.0">
<host:name>ns1.example.tld</host:name>
<host:roid>NS1_EXAMPLE1-REP</host:roid>
<host:status s="linked"/>
<host:status s="clientUpdateProhibited"/>
<host:addr ip="v4">192.0.2.2</host:addr>
<host:addr ip="v4">192.0.2.29</host:addr>
<host:addr ip="v6">1080:0:0:0:8:800:200C:417A</host:addr>
<host:clID>TheRegistrar</host:clID>
<host:crID>NewRegistrar</host:crID>
<host:crDate>1999-04-03T22:00:00.0Z</host:crDate>
<host:upID>NewRegistrar</host:upID>
<host:upDate>1999-12-03T09:00:00.0Z</host:upDate>
<host:trDate>2000-04-08T09:00:00.0Z</host:trDate>
</host:infData>
</resData>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>server-trid</svTRID>
</trID>
</response>
</epp>

View file

@ -0,0 +1,28 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<resData>
<host:infData
xmlns:host="urn:ietf:params:xml:ns:host-1.0">
<host:name>ns1.example.tld</host:name>
<host:roid>NS1_EXAMPLE1-REP</host:roid>
<host:status s="clientUpdateProhibited"/>
<host:addr ip="v4">192.0.2.2</host:addr>
<host:addr ip="v4">192.0.2.29</host:addr>
<host:addr ip="v6">1080:0:0:0:8:800:200C:417A</host:addr>
<host:clID>superclientid</host:clID>
<host:crID>NewRegistrar</host:crID>
<host:crDate>1999-04-03T22:00:00.0Z</host:crDate>
<host:upID>NewRegistrar</host:upID>
<host:upDate>1999-12-03T09:00:00.0Z</host:upDate>
<host:trDate>2000-04-08T09:00:00.0Z</host:trDate>
</host:infData>
</resData>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>server-trid</svTRID>
</trID>
</response>
</epp>

View file

@ -0,0 +1,21 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<update>
<host:update
xmlns:host="urn:ietf:params:xml:ns:host-1.0">
<host:name>%OLD-HOSTNAME%</host:name>
<host:add>
%ADD-HOSTADDRS%
<host:status s="clientUpdateProhibited"/>
</host:add>
<host:rem>
%REM-HOSTADDRS%
</host:rem>
<host:chg>
<host:name>%NEW-HOSTNAME%</host:name>
</host:chg>
</host:update>
</update>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View file

@ -0,0 +1,14 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<update>
<host:update
xmlns:host="urn:ietf:params:xml:ns:host-1.0">
<host:name>ns1.example.tld</host:name>
<host:add>
<host:status s="serverUpdateProhibited"/>
</host:add>
</host:update>
</update>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View file

@ -0,0 +1,18 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<update>
<host:update
xmlns:host="urn:ietf:params:xml:ns:host-1.0">
<host:name>ns1.example.tld</host:name>
<host:add>
<host:addr ip="v4">192.0.2.22</host:addr>
<host:status s="clientUpdateProhibited"/>
</host:add>
<host:rem>
<host:addr ip="v6">1080:0:0:0:8:800:200C:417A</host:addr>
</host:rem>
</host:update>
</update>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View file

@ -0,0 +1,21 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<update>
<host:update
xmlns:host="urn:ietf:params:xml:ns:host-1.0">
<host:name>ns1.example.tld</host:name>
<host:add>
<host:addr ip="v4">192.0.2.22</host:addr>
<host:status s="serverUpdateProhibited"/>
</host:add>
<host:rem>
<host:addr ip="v6">1080:0:0:0:8:800:200C:417A</host:addr>
</host:rem>
<host:chg>
<host:name>ns2.example.tld</host:name>
</host:chg>
</host:update>
</update>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View file

@ -0,0 +1,14 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<update>
<host:update
xmlns:host="urn:ietf:params:xml:ns:host-1.0">
<host:name>ns1.example.com</host:name>
<host:rem>
<host:status s="clientUpdateProhibited"/>
</host:rem>
</host:update>
</update>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View file

@ -0,0 +1,11 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>server-trid</svTRID>
</trID>
</response>
</epp>