/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF 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 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.globo.globodns.cloudstack.resource; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.times; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; import static org.mockito.Mockito.any; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.InOrder; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import com.cloud.agent.api.Answer; import com.globo.globodns.client.GloboDns; import com.globo.globodns.client.api.DomainAPI; import com.globo.globodns.client.api.ExportAPI; import com.globo.globodns.client.api.RecordAPI; import com.globo.globodns.client.model.Domain; import com.globo.globodns.client.model.Record; import com.globo.globodns.cloudstack.commands.CreateOrUpdateDomainCommand; import com.globo.globodns.cloudstack.commands.CreateOrUpdateRecordAndReverseCommand; import com.globo.globodns.cloudstack.commands.RemoveDomainCommand; import com.globo.globodns.cloudstack.commands.RemoveRecordCommand; @DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) public class GloboDnsResourceTest { private GloboDnsResource _globoDnsResource; private GloboDns _globoDnsApi; private DomainAPI _domainApi; private RecordAPI _recordApi; private ExportAPI _exportApi; private static final Long TEMPLATE_ID = 1l; private static long sequenceId = 10l; @Before public void setUp() throws Exception { String name = "GloboDNS"; Map<String, Object> params = new HashMap<String, Object>(); params.put("zoneId", "1"); params.put("guid", "globodns"); params.put("name", name); params.put("url", "http://example.com"); params.put("username", "username"); params.put("password", "password"); _globoDnsResource = new GloboDnsResource(); _globoDnsResource.configure(name, params); _globoDnsApi = spy(_globoDnsResource._globoDns); _globoDnsResource._globoDns = _globoDnsApi; _domainApi = mock(DomainAPI.class); when(_globoDnsApi.getDomainAPI()).thenReturn(_domainApi); _recordApi = mock(RecordAPI.class); when(_globoDnsApi.getRecordAPI()).thenReturn(_recordApi); _exportApi = mock(ExportAPI.class); when(_globoDnsApi.getExportAPI()).thenReturn(_exportApi); } @After public void tearDown() throws Exception { } /////////////////////// // Auxiliary Methods // /////////////////////// private Domain generateFakeDomain(String domainName, boolean reverse) { Domain domain = new Domain(); domain.getDomainAttributes().setId(sequenceId++); domain.getDomainAttributes().setName(domainName); List<Domain> domainList = new ArrayList<Domain>(); domainList.add(domain); if (reverse) { when(_domainApi.listReverseByQuery(eq(domainName))).thenReturn(domainList); } else { when(_domainApi.listByQuery(eq(domainName))).thenReturn(domainList); } return domain; } private Record generateFakeRecord(Domain domain, String recordName, String recordContent, boolean reverse) { Record record = new Record(); if (reverse) { record.getTypePTRRecordAttributes().setName(recordName); record.getTypePTRRecordAttributes().setContent(recordContent); record.getTypePTRRecordAttributes().setDomainId(domain.getId()); record.getTypePTRRecordAttributes().setId(sequenceId++); } else { record.getTypeARecordAttributes().setName(recordName); record.getTypeARecordAttributes().setContent(recordContent); record.getTypeARecordAttributes().setDomainId(domain.getId()); record.getTypeARecordAttributes().setId(sequenceId++); } List<Record> recordList = new ArrayList<Record>(); recordList.add(record); when(_recordApi.listByQuery(eq(domain.getId()), eq(recordName))).thenReturn(recordList); return record; } ///////////////////////// // Create Domain tests // ///////////////////////// @Test public void testCreateDomainWithSuccessWhenDomainDoesntExistAndOverrideIsTrue() throws Exception { String domainName = "domain.name.com"; Domain domain = new Domain(); domain.getDomainAttributes().setId(sequenceId++); domain.getDomainAttributes().setName(domainName); when(_domainApi.createDomain(eq(domain.getName()), eq(TEMPLATE_ID), eq("M"))).thenReturn(domain); Answer answer = _globoDnsResource.execute(new CreateOrUpdateDomainCommand(domainName, TEMPLATE_ID)); assertNotNull(answer); assertEquals(true, answer.getResult()); verify(_exportApi, times(1)).scheduleExport(); } @Test @SuppressWarnings("unused") public void testCreateDomainWillSucceedWhenDomainAlreadyExistsAndOverrideIsFalse() throws Exception { String domainName = "domain.name.com"; Domain domain = generateFakeDomain(domainName, false); Answer answer = _globoDnsResource.execute(new CreateOrUpdateDomainCommand(domainName, TEMPLATE_ID)); assertNotNull(answer); assertEquals(true, answer.getResult()); } ///////////////////////// // Create Record tests // ///////////////////////// @Test @SuppressWarnings("unused") public void testCreateRecordAndReverseWithSuccessWhenDomainExistsAndRecordDoesntExistAndOverrideIsTrue() throws Exception { String recordName = "recordname"; String recordIp = "40.30.20.10"; String domainName = "domain.name.com"; String reverseDomainName = "20.30.40.in-addr.arpa"; String reverseRecordName = "10"; String reverseRecordContent = recordName + "." + domainName; Domain domain = generateFakeDomain(domainName, false); Record record = generateFakeRecord(domain, recordName, recordIp, false); Domain reverseDomain = generateFakeDomain(reverseDomainName, true); Record reverseRecord = generateFakeRecord(reverseDomain, reverseRecordName, reverseRecordContent, true); when(_recordApi.createRecord(eq(domain.getId()), eq(recordName), eq(recordIp), eq("A"))).thenReturn(record); when(_recordApi.createRecord(eq(reverseDomain.getId()), eq(reverseRecordName), eq(reverseRecordContent), eq("PTR"))).thenReturn(record); Answer answer = _globoDnsResource.execute(new CreateOrUpdateRecordAndReverseCommand(recordName, recordIp, domainName, TEMPLATE_ID, true)); assertNotNull(answer); assertEquals(true, answer.getResult()); verify(_exportApi, times(1)).scheduleExport(); } @Test @SuppressWarnings("unused") public void testCreateRecordAndReverseWillFailWhenRecordAlreadyExistsAndOverrideIsFalse() throws Exception { String recordName = "recordname"; String newIp = "40.30.20.10"; String oldIp = "50.40.30.20"; String domainName = "domain.name.com"; Domain domain = generateFakeDomain(domainName, false); Record record = generateFakeRecord(domain, recordName, oldIp, false); Answer answer = _globoDnsResource.execute(new CreateOrUpdateRecordAndReverseCommand(recordName, newIp, domainName, TEMPLATE_ID, false)); assertNotNull(answer); assertEquals(false, answer.getResult()); } @Test @SuppressWarnings("unused") public void testCreateRecordAndReverseWillFailWhenReverseRecordAlreadyExistsAndOverrideIsFalse() throws Exception { String recordName = "recordname"; String recordIp = "40.30.20.10"; String domainName = "domain.name.com"; String reverseDomainName = "20.30.40.in-addr.arpa"; String reverseRecordName = "10"; Domain domain = generateFakeDomain(domainName, false); Record record = generateFakeRecord(domain, recordName, recordIp, false); Domain reverseDomain = generateFakeDomain(reverseDomainName, true); Record reverseRecord = generateFakeRecord(reverseDomain, reverseRecordName, "X", true); Answer answer = _globoDnsResource.execute(new CreateOrUpdateRecordAndReverseCommand(recordName, recordIp, domainName, TEMPLATE_ID, false)); assertNotNull(answer); assertEquals(false, answer.getResult()); } @Test public void testCreateRecordAndReverseWhenDomainDoesNotExist() throws Exception { String recordName = "recordname"; String recordIp = "40.30.20.10"; String domainName = "domain.name.com"; String reverseDomainName = "20.30.40.in-addr.arpa"; String reverseRecordName = "10"; String reverseRecordContent = recordName + "." + domainName; Domain domain = new Domain(); domain.getDomainAttributes().setId(sequenceId++); Domain reverseDomain = new Domain(); reverseDomain.getDomainAttributes().setId(sequenceId++); Record record = new Record(); when(_domainApi.listByQuery(domainName)).thenReturn(new ArrayList<Domain>()); when(_domainApi.createDomain(eq(domainName), eq(TEMPLATE_ID), eq("M"))).thenReturn(domain); when(_recordApi.createRecord(eq(domain.getId()), eq(recordName), eq(recordIp), eq("A"))).thenReturn(record); when(_domainApi.createReverseDomain(eq(reverseDomainName), eq(TEMPLATE_ID), eq("M"))).thenReturn(reverseDomain); when(_recordApi.createRecord(eq(reverseDomain.getId()), eq(reverseRecordName), eq(reverseRecordContent), eq("PTR"))).thenReturn(record); Answer answer = _globoDnsResource.execute(new CreateOrUpdateRecordAndReverseCommand(recordName, recordIp, domainName, TEMPLATE_ID, true)); assertNotNull(answer); assertEquals(true, answer.getResult()); verify(_exportApi, times(1)).scheduleExport(); } @Test public void testCreateRecordAndReverseWhenDomainDoesNotExistAndOverrideIsFalse() throws Exception { String recordName = "recordname"; String recordIp = "40.30.20.10"; String domainName = "domain.name.com"; String reverseDomainName = "20.30.40.in-addr.arpa"; String reverseRecordName = "10"; String reverseRecordContent = recordName + "." + domainName; Domain domain = new Domain(); domain.getDomainAttributes().setId(sequenceId++); Domain reverseDomain = new Domain(); reverseDomain.getDomainAttributes().setId(sequenceId++); Record record = new Record(); when(_domainApi.listByQuery(domainName)).thenReturn(new ArrayList<Domain>()); when(_domainApi.createDomain(eq(domainName), eq(TEMPLATE_ID), eq("M"))).thenReturn(domain); when(_recordApi.createRecord(eq(domain.getId()), eq(recordName), eq(recordIp), eq("A"))).thenReturn(record); when(_domainApi.createReverseDomain(eq(reverseDomainName), eq(TEMPLATE_ID), eq("M"))).thenReturn(reverseDomain); when(_recordApi.createRecord(eq(reverseDomain.getId()), eq(reverseRecordName), eq(reverseRecordContent), eq("PTR"))).thenReturn(record); Answer answer = _globoDnsResource.execute(new CreateOrUpdateRecordAndReverseCommand(recordName, recordIp, domainName, TEMPLATE_ID, false)); assertNotNull(answer); assertEquals(true, answer.getResult()); verify(_exportApi, times(1)).scheduleExport(); } ///////////////////////// // Update Record tests // ///////////////////////// @Test public void testUpdateRecordAndReverseWhenDomainExistsAndOverrideIsTrue() throws Exception { String recordName = "recordname"; String oldRecordIp = "40.30.20.10"; String newRecordIp = "50.40.30.20"; String domainName = "domain.name.com"; String reverseDomainName = "30.40.50.in-addr.arpa"; String reverseRecordName = "20"; String reverseRecordContent = recordName + "." + domainName; Domain domain = generateFakeDomain(domainName, false); Record record = generateFakeRecord(domain, recordName, oldRecordIp, false); Domain reverseDomain = generateFakeDomain(reverseDomainName, true); Record reverseRecord = generateFakeRecord(reverseDomain, reverseRecordName, "X", true); Answer answer = _globoDnsResource.execute(new CreateOrUpdateRecordAndReverseCommand(recordName, newRecordIp, domainName, TEMPLATE_ID, true)); // ensure calls in sequence to ensure this call are the only ones. InOrder inOrder = inOrder(_recordApi); inOrder.verify(_recordApi, times(1)).updateRecord(eq(record.getId()), eq(domain.getId()), eq(recordName), eq(newRecordIp)); inOrder.verify(_recordApi, times(1)).updateRecord(eq(reverseRecord.getId()), eq(reverseDomain.getId()), eq(reverseRecordName), eq(reverseRecordContent)); assertNotNull(answer); assertEquals(true, answer.getResult()); verify(_exportApi, times(1)).scheduleExport(); } ///////////////////////// // Remove Record tests // ///////////////////////// @Test public void testRemoveRecordWhenRecordExists() throws Exception { String recordName = "recordname"; String recordIp = "40.30.20.10"; String domainName = "domain.name.com"; String reverseDomainName = "20.30.40.in-addr.arpa"; String reverseRecordName = "10"; String reverseRecordContent = recordName + "." + domainName; Domain domain = generateFakeDomain(domainName, false); Record record = generateFakeRecord(domain, recordName, recordIp, false); Domain reverseDomain = generateFakeDomain(reverseDomainName, true); Record reverseRecord = generateFakeRecord(reverseDomain, reverseRecordName, reverseRecordContent, true); Answer answer = _globoDnsResource.execute(new RemoveRecordCommand(recordName, recordIp, domainName, true)); assertNotNull(answer); assertEquals(true, answer.getResult()); verify(_recordApi, times(1)).removeRecord(eq(record.getId())); verify(_recordApi, times(1)).removeRecord(eq(reverseRecord.getId())); verify(_exportApi, times(1)).scheduleExport(); } @Test public void testRemoveRecordWithSuccessAndReverseRecordNotRemovedWhenReverseRecordExistsWithDifferentValueAndOverrideIsFalse() throws Exception { String recordName = "recordname"; String recordIp = "40.30.20.10"; String domainName = "domain.name.com"; String reverseDomainName = "20.30.40.in-addr.arpa"; String reverseRecordName = "10"; Domain domain = generateFakeDomain(domainName, false); Record record = generateFakeRecord(domain, recordName, recordIp, false); Domain reverseDomain = generateFakeDomain(reverseDomainName, true); Record reverseRecord = generateFakeRecord(reverseDomain, reverseRecordName, "X", true); Answer answer = _globoDnsResource.execute(new RemoveRecordCommand(recordName, recordIp, domainName, false)); assertEquals(true, answer.getResult()); verify(_recordApi, times(1)).removeRecord(eq(record.getId())); verify(_recordApi, never()).removeRecord(eq(reverseRecord.getId())); verify(_exportApi, times(1)).scheduleExport(); } @Test public void testRemoveReverseRecordButNotRemoveRecordWhenRecordExistsWithDifferentValueAndOverrideIsFalse() throws Exception { String recordName = "recordname"; String recordIp = "40.30.20.10"; String domainName = "domain.name.com"; String reverseDomainName = "20.30.40.in-addr.arpa"; String reverseRecordName = "10"; String reverseRecordContent = recordName + "." + domainName; Domain domain = generateFakeDomain(domainName, false); Record record = generateFakeRecord(domain, recordName, "X", false); Domain reverseDomain = generateFakeDomain(reverseDomainName, true); Record reverseRecord = generateFakeRecord(reverseDomain, reverseRecordName, reverseRecordContent, true); Answer answer = _globoDnsResource.execute(new RemoveRecordCommand(recordName, recordIp, domainName, false)); assertEquals(true, answer.getResult()); verify(_recordApi, never()).removeRecord(eq(record.getId())); verify(_recordApi, times(1)).removeRecord(eq(reverseRecord.getId())); verify(_exportApi, times(1)).scheduleExport(); } ///////////////////////// // Remove Domain tests // ///////////////////////// @Test public void testRemoveDomainWithSuccessButDomainKeptWhenDomainExistsAndThereAreRecordsAndOverrideIsFalse() throws Exception { String recordName = "recordname"; String recordIp = "40.30.20.10"; String domainName = "domain.name.com"; Domain domain = generateFakeDomain(domainName, false); Record record = generateFakeRecord(domain, recordName, "X", false); when(_recordApi.listAll(domain.getId())).thenReturn(Arrays.asList(record)); Answer answer = _globoDnsResource.execute(new RemoveRecordCommand(recordName, recordIp, domainName, false)); assertEquals(true, answer.getResult()); verify(_domainApi, never()).removeDomain(any(Long.class)); verify(_exportApi, never()).scheduleExport(); } @Test public void testRemoveDomainWithSuccessWhenDomainExistsAndThereAreOnlyNSRecordsAndOverrideIsFalse() throws Exception { String domainName = "domain.name.com"; Domain domain = generateFakeDomain(domainName, false); List<Record> recordList = new ArrayList<Record>(); for (int i = 0; i < 10; i++) { Record record = new Record(); record.getTypeNSRecordAttributes().setDomainId(domain.getId()); record.getTypeNSRecordAttributes().setId(sequenceId++); record.getTypeNSRecordAttributes().setType("NS"); recordList.add(record); } when(_recordApi.listAll(domain.getId())).thenReturn(recordList); Answer answer = _globoDnsResource.execute(new RemoveDomainCommand(domainName, false)); assertEquals(true, answer.getResult()); verify(_domainApi, times(1)).removeDomain(eq(domain.getId())); verify(_exportApi, times(1)).scheduleExport(); } @Test public void testRemoveDomainWithSuccessWhenDomainExistsAndThereAreRecordsAndOverrideIsTrue() throws Exception { String domainName = "domain.name.com"; Domain domain = generateFakeDomain(domainName, false); List<Record> recordList = new ArrayList<Record>(); for (int i = 0; i < 10; i++) { Record record = new Record(); record.getTypeNSRecordAttributes().setDomainId(domain.getId()); record.getTypeNSRecordAttributes().setId(sequenceId++); record.getTypeNSRecordAttributes().setType(new String[] {"A", "NS", "PTR"}[i % 3]); recordList.add(record); } when(_recordApi.listAll(domain.getId())).thenReturn(recordList); Answer answer = _globoDnsResource.execute(new RemoveDomainCommand(domainName, true)); assertEquals(true, answer.getResult()); verify(_domainApi, times(1)).removeDomain(eq(domain.getId())); verify(_exportApi, times(1)).scheduleExport(); } }