/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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 WATCANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.ultradns.ws.features;
import static java.util.logging.Logger.getAnonymousLogger;
import static org.jclouds.ultradns.ws.domain.TrafficControllerPool.RecordType.IPV4;
import static org.jclouds.ultradns.ws.domain.TrafficControllerPoolRecordDetail.Status.UNRECOGNIZED;
import static org.jclouds.ultradns.ws.predicates.TrafficControllerPoolPredicates.idEqualTo;
import static org.jclouds.ultradns.ws.predicates.TrafficControllerPoolPredicates.recordIdEqualTo;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import org.jclouds.rest.ResourceNotFoundException;
import org.jclouds.ultradns.ws.UltraDNSWSExceptions.ResourceAlreadyExistsException;
import org.jclouds.ultradns.ws.domain.PoolRecordSpec;
import org.jclouds.ultradns.ws.domain.TrafficControllerPool;
import org.jclouds.ultradns.ws.domain.TrafficControllerPoolRecord;
import org.jclouds.ultradns.ws.domain.TrafficControllerPoolRecordDetail;
import org.jclouds.ultradns.ws.domain.UpdatePoolRecord;
import org.jclouds.ultradns.ws.domain.Zone;
import org.jclouds.ultradns.ws.internal.BaseUltraDNSWSApiLiveTest;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
/**
* @author Adrian Cole
*/
@Test(groups = "live", singleThreaded = true, testName = "TrafficControllerPoolApiLiveTest")
public class TrafficControllerPoolApiLiveTest extends BaseUltraDNSWSApiLiveTest {
@Override
@BeforeClass(groups = { "integration", "live" })
public void setup() {
super.setup();
createZone();
}
private void checkTCPool(TrafficControllerPool pool) {
assertNotNull(pool.getZoneId(), "ZoneId cannot be null " + pool);
assertNotNull(pool.getId(), "Id cannot be null " + pool);
assertNotNull(pool.getName(), "Name cannot be null " + pool);
assertNotNull(pool.getDName(), "DName cannot be null " + pool);
assertEquals(api(zoneName).getNameByDName(pool.getDName()), pool.getName());
}
@Test
public void testListTCPools() {
for (Zone zone : api.getZoneApi().listByAccount(account.getId())) {
for (TrafficControllerPool pool : api(zone.getName()).list()) {
checkTCPool(pool);
}
}
}
@Test
public void testListTCPoolRecords() {
for (Zone zone : api.getZoneApi().listByAccount(account.getId())) {
for (TrafficControllerPool pool : api(zone.getName()).list()) {
for (TrafficControllerPoolRecordDetail record : api(zone.getName()).listRecords(pool.getId())) {
checkPoolRecordConsistent(zone.getName(), record);
}
}
}
}
private TrafficControllerPoolRecordDetail checkPoolRecordConsistent(String zoneName, TrafficControllerPoolRecordDetail record) {
Optional<TrafficControllerPool> pool = getPoolByZoneAndId(zoneName, record.getPoolId());
assertTrue(pool.isPresent(), "could not get pool for " + record);
assertEquals(record.getDescription(), pool.get().getName());
PoolRecordSpec spec = checkPoolRecordSpec(api(zoneName).getRecordSpec(record.getId()));
assertEquals(record.getDescription(), spec.getDescription());
assertEquals(record.getWeight(), spec.getWeight());
assertEquals(record.isProbingEnabled(), spec.isProbingEnabled());
return checkTrafficControllerPoolRecord(record);
}
static TrafficControllerPoolRecordDetail checkTrafficControllerPoolRecord(TrafficControllerPoolRecordDetail record) {
assertNotNull(record.getId(), "Id cannot be null for " + record);
assertNotNull(record.getPoolId(), "PoolId cannot be null for " + record);
assertNotNull(record.getRecord().getRData(), "Record.RData cannot be null for " + record);
assertNotNull(record.getRecord().getType(), "Record.Type cannot be null for " + record);
assertTrue(record.getWeight() >= 0, "Weight must be unsigned for " + record);
assertTrue(record.getPriority() >= 0, "Priority must be unsigned for " + record);
assertNotNull(record.getStatus(), "Status cannot be null for " + record);
assertTrue(record.getStatus() != UNRECOGNIZED, "unrecognized status for " + record);
assertNotNull(record.getDescription(), "Description cannot be null for " + record);
return record;
}
static PoolRecordSpec checkPoolRecordSpec(PoolRecordSpec record) {
assertNotNull(record.getDescription(), "Description cannot be null for " + record);
assertNotNull(record.getState(), "State cannot be null for " + record);
// TODO: collect all possible states then consider enum
assertTrue(ImmutableSet.of("Normal", "Normal-NoTest").contains(record.getState()), "Unknown State for " + record);
assertTrue(record.getWeight() >= 0, "Weight must be unsigned for " + record);
assertTrue(record.getFailOverDelay() >= 0, "failOverDelay must be unsigned for " + record);
assertTrue(record.getThreshold() >= 0, "threshold must be unsigned for " + record);
assertTrue(record.getTTL() >= 0, "ttl must be unsigned for " + record);
return record;
}
@Test(expectedExceptions = ResourceNotFoundException.class, expectedExceptionsMessageRegExp = "Zone does not exist in the system.")
public void testListTCPoolsWhenZoneIdNotFound() {
api("AAAAAAAAAAAAAAAA").list();
}
@Test
public void testDeleteWhenNotFound() {
api(zoneName).delete("06063D9C54C5AE09");
}
@Test
public void testDeleteRecordWhenNotFound() {
api(zoneName).deleteRecord("06063D9C54C5AE09");
}
@Test
public void testGetNameByDNameWhenNotFound() {
assertNull(api(zoneName).getNameByDName("www.razzledazzle.cn."));
}
@Test
public void testGetRecordSpecWhenNotFound() {
assertNull(api(zoneName).getRecordSpec("06063D9C54C5AE09"));
}
@Test(expectedExceptions = ResourceNotFoundException.class, expectedExceptionsMessageRegExp = "Pool Record does not exist.")
public void testUpdateRecordWhenNotFound() {
api(zoneName).updateRecord("06063D9C54C5AE09",
UpdatePoolRecord.builder().rdata("www.foo.com.").mode("Normal").build());
}
String dname = "www.tcpool." + zoneName;
String poolId;
@Test
public void testCreatePool() {
poolId = api(zoneName).createForDNameAndType("pool", dname, IPV4.getCode());
getAnonymousLogger().info("created tc pool: " + poolId);
try {
api(zoneName).createForDNameAndType("pool", dname, IPV4.getCode());
fail();
} catch (ResourceAlreadyExistsException e) {
}
// ensure there's only one pool for a dname
try {
api(zoneName).createForDNameAndType("pool1", dname, IPV4.getCode());
fail();
} catch (ResourceAlreadyExistsException e) {
}
Optional<TrafficControllerPool> pool = getPoolByZoneAndId(zoneName, poolId);
assertTrue(pool.isPresent());
assertEquals(pool.get().getId(), poolId);
assertEquals(pool.get().getName(), "pool");
assertEquals(pool.get().getDName(), dname);
checkTCPool(pool.get());
}
@DataProvider(name = "records")
public Object[][] createRecords() {
Object[][] records = new Object[2][4];
records[0][0] = "1.2.3.4";
records[0][1] = "A";
records[0][2] = 60;
records[0][3] = Optional.of(98);
records[1][0] = "5.6.7.8";
records[1][1] = "A";
records[1][2] = 60;
records[1][3] = Optional.of(2);
return records;
}
@Test(dependsOnMethods = "testCreatePool", dataProvider = "records")
public TrafficControllerPoolRecordDetail addRecordToPool(String rdata, String type, int ttl, Optional<Integer> weight) {
String recordId;
if (weight.isPresent()) {
recordId = api(zoneName).addRecordToPoolWithTTLAndWeight(rdata, poolId, ttl, weight.get());
} else {
recordId = api(zoneName).addRecordToPoolWithTTL(rdata, poolId, ttl);
}
getAnonymousLogger().info("created " + type + " record: " + recordId);
TrafficControllerPoolRecordDetail record = checkPoolRecordConsistent(zoneName, getRecordById(recordId).get());
PoolRecordSpec recordSpec = checkPoolRecordSpec(api(zoneName).getRecordSpec(recordId));
assertEquals(record.getRecord(), TrafficControllerPoolRecord.create(type, rdata));
assertEquals(record.getWeight(), weight.or(2).intValue());
assertEquals(recordSpec.getTTL(), ttl);
return record;
}
String cname1;
String cname2;
@Test(dependsOnMethods = "testCreatePool")
public void addCNAMERecordsToPool() {
cname1 = addRecordToPool("www.foo.com.", "CNAME", 30, Optional.<Integer> absent()).getId();
try {
api(zoneName).addRecordToPoolWithTTL("www.foo.com.", poolId, 30);
fail();
} catch (ResourceAlreadyExistsException e) {
}
cname2 = addRecordToPool("www.bar.com.", "CNAME", 30, Optional.<Integer> absent()).getId();
}
@Test(dependsOnMethods = "addCNAMERecordsToPool")
public void testUpdateRecord() {
PoolRecordSpec spec = api(zoneName).getRecordSpec(cname2);
UpdatePoolRecord update = UpdatePoolRecord.builder().from(spec)
.rdata("www.baz.com.")
.weight(98)
.ttl(200).build();
api(zoneName).updateRecord(cname2, update);
TrafficControllerPoolRecordDetail record = getRecordById(cname2).get();
assertEquals(record.getRecord().getRData(), "www.baz.com.");
spec = api(zoneName).getRecordSpec(cname2);
assertEquals(spec.getWeight(), 98);
assertEquals(spec.getTTL(), 200);
}
@Test(dependsOnMethods = "testUpdateRecord")
public void testDeleteRecord() {
api(zoneName).deleteRecord(cname1);
assertFalse(getRecordById(cname1).isPresent());
assertTrue(getRecordById(cname2).isPresent());
}
@Test(dependsOnMethods = "testDeleteRecord")
public void testDeletePool() {
api(zoneName).delete(poolId);
assertFalse(getPoolByZoneAndId(zoneName, poolId).isPresent());
}
private Optional<TrafficControllerPoolRecordDetail> getRecordById(String recordId) {
return api(zoneName).listRecords(poolId).firstMatch(recordIdEqualTo(recordId));
}
private Optional<TrafficControllerPool> getPoolByZoneAndId(String zoneName, final String poolId) {
return api(zoneName).list().firstMatch(idEqualTo(poolId));
}
private TrafficControllerPoolApi api(String zoneName) {
return api.getTrafficControllerPoolApiForZone(zoneName);
}
@Override
@AfterClass(groups = { "integration", "live" })
protected void tearDown() {
if (poolId != null)
api(zoneName).delete(poolId);
super.tearDown();
}
}