blob: c45c02484eb6a92fa1692894be32da9a6e2c8b7f [file] [log] [blame]
/*
* 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 org.apache.qpid.server.store;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.text.NumberFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.junit.Before;
import org.junit.Test;
import org.apache.qpid.server.configuration.CommonProperties;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.OverflowPolicy;
import org.apache.qpid.server.model.VirtualHostNode;
import org.apache.qpid.test.utils.UnitTestBase;
public class VirtualHostStoreUpgraderAndRecovererTest extends UnitTestBase
{
private VirtualHostNode<?> _virtualHostNode;
private VirtualHostStoreUpgraderAndRecoverer _upgraderAndRecoverer;
private DurableConfigurationStore _store;
@Before
public void setUp() throws Exception
{
final Broker broker = mock(Broker.class);
_virtualHostNode = mock(VirtualHostNode.class);
when(_virtualHostNode.getParent()).thenReturn(broker);
_store = mock(DurableConfigurationStore.class);
_upgraderAndRecoverer = new VirtualHostStoreUpgraderAndRecoverer(_virtualHostNode);
}
@Test
public void testUpgradeFlowControlFrom_6_1() throws Exception
{
Map<String, Object> rootAttributes = new HashMap<>();
rootAttributes.put("modelVersion", "6.1");
rootAttributes.put("name", "root");
ConfiguredObjectRecord rootRecord =
new ConfiguredObjectRecordImpl(UUID.randomUUID(), "VirtualHost", rootAttributes);
Map<String, Object> queueAttributes = new HashMap<>();
queueAttributes.put("name", "queue");
queueAttributes.put("queueFlowControlSizeBytes", 1000);
queueAttributes.put("queueFlowResumeSizeBytes", 700);
ConfiguredObjectRecord queueRecord = new ConfiguredObjectRecordImpl(UUID.randomUUID(), "Queue", queueAttributes,
Collections.singletonMap(rootRecord.getType(),
rootRecord.getId()));
List<ConfiguredObjectRecord> records = Arrays.asList(rootRecord, queueRecord);
List<ConfiguredObjectRecord> upgradedRecords =
_upgraderAndRecoverer.upgrade(_store, records, "VirtualHost", "modelVersion");
ConfiguredObjectRecord upgradedQueueRecord = findRecordById(queueRecord.getId(), upgradedRecords);
assertNotNull("Upgraded queue record not found ", upgradedQueueRecord);
Map<String, Object> upgradedAttributes = upgradedQueueRecord.getAttributes();
assertNotNull("Upgraded attributes not found", upgradedAttributes);
assertEquals("Unexpected maximumQueueDepthBytes", 1000, upgradedAttributes.get("maximumQueueDepthBytes"));
NumberFormat formatter = NumberFormat.getInstance();
formatter.setMinimumFractionDigits(2);
assertEquals("Unexpected queue.queueFlowResumeLimit",
formatter.format(70L),
((Map<String, String>) upgradedAttributes.get("context")).get("queue.queueFlowResumeLimit"));
assertEquals("Unexpected overflowPolicy",
OverflowPolicy.PRODUCER_FLOW_CONTROL.name(),
String.valueOf(upgradedAttributes.get("overflowPolicy")));
}
@Test
public void testUpgradeQueueAlternateExchangeFrom_6_1() throws Exception
{
Map<String, Object> rootAttributes = new HashMap<>();
rootAttributes.put("modelVersion", "6.1");
rootAttributes.put("name", "root");
ConfiguredObjectRecord rootRecord =
new ConfiguredObjectRecordImpl(UUID.randomUUID(), "VirtualHost", rootAttributes);
Map<String, Object> queueAttributes = new HashMap<>();
queueAttributes.put("name", "queue");
queueAttributes.put("alternateExchange", "testExchange");
ConfiguredObjectRecord queueRecord = new ConfiguredObjectRecordImpl(UUID.randomUUID(), "Queue", queueAttributes,
Collections.singletonMap(rootRecord.getType(),
rootRecord.getId()));
final Map<String, Object> exchangeAttributes = new HashMap<>();
exchangeAttributes.put("name", "testExchange");
ConfiguredObjectRecord exchangeRecord = new ConfiguredObjectRecordImpl(UUID.randomUUID(), "Exchange", exchangeAttributes,
Collections.singletonMap(rootRecord.getType(),
rootRecord.getId()));
List<ConfiguredObjectRecord> records = Arrays.asList(rootRecord, queueRecord, exchangeRecord);
List<ConfiguredObjectRecord> upgradedRecords =
_upgraderAndRecoverer.upgrade(_store, records, "VirtualHost", "modelVersion");
ConfiguredObjectRecord upgradedQueueRecord = findRecordById(queueRecord.getId(), upgradedRecords);
assertNotNull("Upgraded queue record not found ", upgradedQueueRecord);
Map<String, Object> upgradedAttributes = upgradedQueueRecord.getAttributes();
assertNotNull("Upgraded attributes not found", upgradedAttributes);
assertTrue("Attribute 'alternateBinding' was not added",
upgradedAttributes.containsKey("alternateBinding"));
assertEquals("Unexpected alternateBinding",
new HashMap<>(Collections.singletonMap("destination", "testExchange")),
new HashMap<>(((Map<String, String>) upgradedAttributes.get("alternateBinding"))));
assertFalse("Attribute 'alternateExchange' was not removed",
upgradedAttributes.containsKey("alternateExchange"));
}
@Test
public void testUpgradeExchangeAlternateExchangeFrom_6_1() throws Exception
{
Map<String, Object> rootAttributes = new HashMap<>();
rootAttributes.put("modelVersion", "6.1");
rootAttributes.put("name", "root");
ConfiguredObjectRecord rootRecord =
new ConfiguredObjectRecordImpl(UUID.randomUUID(), "VirtualHost", rootAttributes);
final Map<String, Object> alternateExchangeAttributes = new HashMap<>();
alternateExchangeAttributes.put("name", "testExchange");
ConfiguredObjectRecord alternateExchangeRecord = new ConfiguredObjectRecordImpl(UUID.randomUUID(), "Exchange", alternateExchangeAttributes,
Collections.singletonMap(rootRecord.getType(),
rootRecord.getId()));
Map<String, Object> exchangeAttributes = new HashMap<>();
exchangeAttributes.put("name", "exchange");
exchangeAttributes.put("alternateExchange", "testExchange");
ConfiguredObjectRecord exchangeRecord = new ConfiguredObjectRecordImpl(UUID.randomUUID(), "Exchange", exchangeAttributes,
Collections.singletonMap(rootRecord.getType(),
rootRecord.getId()));
List<ConfiguredObjectRecord> records = Arrays.asList(rootRecord, exchangeRecord, alternateExchangeRecord);
List<ConfiguredObjectRecord> upgradedRecords =
_upgraderAndRecoverer.upgrade(_store, records, "VirtualHost", "modelVersion");
ConfiguredObjectRecord upgradedQueueRecord = findRecordById(exchangeRecord.getId(), upgradedRecords);
assertNotNull("Upgraded exchange record not found ", upgradedQueueRecord);
Map<String, Object> upgradedAttributes = upgradedQueueRecord.getAttributes();
assertNotNull("Upgraded attributes not found", upgradedAttributes);
assertTrue("Attribute 'alternateBinding' was not added",
upgradedAttributes.containsKey("alternateBinding"));
assertEquals("Unexpected alternateBinding",
new HashMap<>(Collections.singletonMap("destination", "testExchange")),
new HashMap<>(((Map<String, String>) upgradedAttributes.get("alternateBinding"))));
assertFalse("Attribute 'alternateExchange' was not removed",
upgradedAttributes.containsKey("alternateExchange"));
}
@Test
public void testUpgradeExchangeAlternateExchangeSpecifiedWithUUIDFrom_6_1() throws Exception
{
Map<String, Object> rootAttributes = new HashMap<>();
rootAttributes.put("modelVersion", "6.1");
rootAttributes.put("name", "root");
ConfiguredObjectRecord rootRecord =
new ConfiguredObjectRecordImpl(UUID.randomUUID(), "VirtualHost", rootAttributes);
final Map<String, Object> alternateExchangeAttributes = new HashMap<>();
alternateExchangeAttributes.put("name", "testExchange");
UUID alternateExchangeId = UUID.randomUUID();
ConfiguredObjectRecord alternateExchangeRecord = new ConfiguredObjectRecordImpl(alternateExchangeId, "Exchange", alternateExchangeAttributes,
Collections.singletonMap(rootRecord.getType(),
rootRecord.getId()));
Map<String, Object> exchangeAttributes = new HashMap<>();
exchangeAttributes.put("name", "exchange");
exchangeAttributes.put("alternateExchange", alternateExchangeId.toString());
ConfiguredObjectRecord exchangeRecord = new ConfiguredObjectRecordImpl(UUID.randomUUID(), "Exchange", exchangeAttributes,
Collections.singletonMap(rootRecord.getType(),
rootRecord.getId()));
List<ConfiguredObjectRecord> records = Arrays.asList(rootRecord, exchangeRecord, alternateExchangeRecord);
List<ConfiguredObjectRecord> upgradedRecords =
_upgraderAndRecoverer.upgrade(_store, records, "VirtualHost", "modelVersion");
ConfiguredObjectRecord upgradedQueueRecord = findRecordById(exchangeRecord.getId(), upgradedRecords);
assertNotNull("Upgraded exchange record not found ", upgradedQueueRecord);
Map<String, Object> upgradedAttributes = upgradedQueueRecord.getAttributes();
assertNotNull("Upgraded attributes not found", upgradedAttributes);
assertTrue("Attribute 'alternateBinding' was not added",
upgradedAttributes.containsKey("alternateBinding"));
assertEquals("Unexpected alternateBinding",
new HashMap<>(Collections.singletonMap("destination", "testExchange")),
new HashMap<>(((Map<String, String>) upgradedAttributes.get("alternateBinding"))));
assertFalse("Attribute 'alternateExchange' was not removed",
upgradedAttributes.containsKey("alternateExchange"));
}
@Test
public void testUpgradeQueueSharedMessageGroupsFrom_6_1() throws Exception
{
Map<String, Object> rootAttributes = new HashMap<>();
rootAttributes.put("modelVersion", "6.1");
rootAttributes.put("name", "root");
ConfiguredObjectRecord rootRecord =
new ConfiguredObjectRecordImpl(UUID.randomUUID(), "VirtualHost", rootAttributes);
Map<String, Object> queueAttributes = new HashMap<>();
queueAttributes.put("messageGroupKey", "myheader");
queueAttributes.put("messageGroupSharedGroups", true);
ConfiguredObjectRecord queueRecord = new ConfiguredObjectRecordImpl(UUID.randomUUID(), "Queue", queueAttributes,
Collections.singletonMap(rootRecord.getType(),
rootRecord.getId()));
final Map<String, Object> exchangeAttributes = new HashMap<>();
exchangeAttributes.put("name", "testExchange");
ConfiguredObjectRecord exchangeRecord = new ConfiguredObjectRecordImpl(UUID.randomUUID(), "Exchange", exchangeAttributes,
Collections.singletonMap(rootRecord.getType(),
rootRecord.getId()));
List<ConfiguredObjectRecord> records = Arrays.asList(rootRecord, queueRecord, exchangeRecord);
List<ConfiguredObjectRecord> upgradedRecords =
_upgraderAndRecoverer.upgrade(_store, records, "VirtualHost", "modelVersion");
ConfiguredObjectRecord upgradedQueueRecord = findRecordById(queueRecord.getId(), upgradedRecords);
assertNotNull("Upgraded queue record not found ", upgradedQueueRecord);
Map<String, Object> upgradedAttributes = upgradedQueueRecord.getAttributes();
assertNotNull("Upgraded attributes not found", upgradedAttributes);
assertFalse("Attribute 'messageGroupKey' was not removed",
upgradedAttributes.containsKey("messageGroupKey"));
assertFalse("Attribute 'messageGroupSharedGroups' was not removed",
upgradedAttributes.containsKey("messageGroupSharedGroups"));
assertTrue("Attribute 'messageGroupKeyOverride' was not added",
upgradedAttributes.containsKey("messageGroupKeyOverride"));
assertEquals("Unexpected messageGroupKeyOverride",
"myheader",
upgradedAttributes.get("messageGroupKeyOverride"));
assertTrue("Attribute 'messageGroupType' was not added",
upgradedAttributes.containsKey("messageGroupType"));
assertEquals("Unexpected messageGroupType", "SHARED_GROUPS", upgradedAttributes.get("messageGroupType"));
}
@Test
public void testUpgradeQueueStandardMessageGroupsFrom_6_1() throws Exception
{
Map<String, Object> rootAttributes = new HashMap<>();
rootAttributes.put("modelVersion", "6.1");
rootAttributes.put("name", "root");
ConfiguredObjectRecord rootRecord =
new ConfiguredObjectRecordImpl(UUID.randomUUID(), "VirtualHost", rootAttributes);
Map<String, Object> queueAttributes = new HashMap<>();
queueAttributes.put("messageGroupKey", "JMSXGroupId");
queueAttributes.put("messageGroupSharedGroups", false);
ConfiguredObjectRecord queueRecord = new ConfiguredObjectRecordImpl(UUID.randomUUID(), "Queue", queueAttributes,
Collections.singletonMap(rootRecord.getType(),
rootRecord.getId()));
final Map<String, Object> exchangeAttributes = new HashMap<>();
exchangeAttributes.put("name", "testExchange");
ConfiguredObjectRecord exchangeRecord = new ConfiguredObjectRecordImpl(UUID.randomUUID(), "Exchange", exchangeAttributes,
Collections.singletonMap(rootRecord.getType(),
rootRecord.getId()));
List<ConfiguredObjectRecord> records = Arrays.asList(rootRecord, queueRecord, exchangeRecord);
List<ConfiguredObjectRecord> upgradedRecords =
_upgraderAndRecoverer.upgrade(_store, records, "VirtualHost", "modelVersion");
ConfiguredObjectRecord upgradedQueueRecord = findRecordById(queueRecord.getId(), upgradedRecords);
assertNotNull("Upgraded queue record not found ", upgradedQueueRecord);
Map<String, Object> upgradedAttributes = upgradedQueueRecord.getAttributes();
assertNotNull("Upgraded attributes not found", upgradedAttributes);
assertFalse("Attribute 'messageGroupKey' was not removed",
upgradedAttributes.containsKey("messageGroupKey"));
assertFalse("Attribute 'messageGroupSharedGroups' was not removed",
upgradedAttributes.containsKey("messageGroupSharedGroups"));
assertFalse("Attribute 'messageGroupKeyOverride' was added",
upgradedAttributes.containsKey("messageGroupKeyOverride"));
assertTrue("Attribute 'messageGroupType' was not added",
upgradedAttributes.containsKey("messageGroupType"));
assertEquals("Unexpected messageGroupType", "STANDARD", upgradedAttributes.get("messageGroupType"));
}
@Test
public void testContextVariableUpgradeForTLSProtocolsSetOnVirtualHost() throws Exception
{
final Map<String, String> context = new HashMap<>();
context.put("qpid.security.tls.protocolWhiteList", ".*");
context.put("qpid.security.tls.protocolBlackList", "Ssl.*");
final Map<String, Object> rootAttributes = new HashMap<>();
rootAttributes.put("modelVersion", "8.0");
rootAttributes.put("name", "root");
rootAttributes.put("context", context);
final ConfiguredObjectRecord rootRecord = new ConfiguredObjectRecordImpl(UUID.randomUUID(),
"VirtualHost",
rootAttributes);
final List<ConfiguredObjectRecord> upgradedRecords =
_upgraderAndRecoverer.upgrade(_store,
Collections.singletonList(rootRecord),
"VirtualHost",
"modelVersion");
final Map<String, Object> newContext = getContextForRecordWithGivenId(rootRecord.getId(), upgradedRecords);
assertEquals(".*", newContext.get(CommonProperties.QPID_SECURITY_TLS_PROTOCOL_ALLOW_LIST));
assertEquals("Ssl.*", newContext.get(CommonProperties.QPID_SECURITY_TLS_PROTOCOL_DENY_LIST));
}
@Test
public void testContextVariableUpgradeForTLSCipherSuitesSetOnVirtualHostAccessControlProvider() throws Exception
{
final Map<String, Object> rootAttributes = new HashMap<>();
rootAttributes.put("modelVersion", "8.0");
rootAttributes.put("name", "root");
final ConfiguredObjectRecord rootRecord =
new ConfiguredObjectRecordImpl(UUID.randomUUID(), "VirtualHost", rootAttributes);
final Map<String, String> context = new HashMap<>();
context.put("qpid.security.tls.cipherSuiteWhiteList", ".*");
context.put("qpid.security.tls.cipherSuiteBlackList", "Ssl.*");
final ConfiguredObjectRecord accessControlProviderRecord =
createMockRecordForGivenCategoryTypeAndContext("VirtualHostAccessControlProvider", "test", context);
final List<ConfiguredObjectRecord> records = Arrays.asList(rootRecord, accessControlProviderRecord);
final List<ConfiguredObjectRecord> upgradedRecords =
_upgraderAndRecoverer.upgrade(_store, records, "VirtualHost", "modelVersion");
final Map<String, Object> newContext =
getContextForRecordWithGivenId(accessControlProviderRecord.getId(), upgradedRecords);
assertEquals(".*", newContext.get(CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_ALLOW_LIST));
assertEquals("Ssl.*", newContext.get(CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_DENY_LIST));
}
private ConfiguredObjectRecord findRecordById(UUID id, List<ConfiguredObjectRecord> records)
{
for (ConfiguredObjectRecord record : records)
{
if (id.equals(record.getId()))
{
return record;
}
}
return null;
}
private ConfiguredObjectRecord createMockRecordForGivenCategoryTypeAndContext(final String category,
final String type,
final Map<String, String> context)
{
final ConfiguredObjectRecord record = mock(ConfiguredObjectRecord.class);
when(record.getId()).thenReturn(UUID.randomUUID());
when(record.getType()).thenReturn(category);
final Map<String, Object> attributes = new HashMap<>();
attributes.put("name", getTestName());
attributes.put("type", type);
attributes.put("context", context);
when(record.getAttributes()).thenReturn(attributes);
return record;
}
private Map<String, Object> getContextForRecordWithGivenId(final UUID rootRecordId,
final List<ConfiguredObjectRecord> upgradedRecords)
{
final ConfiguredObjectRecord upgradedRecord = findRecordById(rootRecordId, upgradedRecords);
assertNotNull(upgradedRecord);
final Map<String, Object> attributes = upgradedRecord.getAttributes();
assertNotNull(attributes);
final Object context = attributes.get("context");
assertTrue(context instanceof Map);
@SuppressWarnings("unchecked")
final Map<String, Object> contextMap = (Map<String, Object>) context;
return contextMap;
}
}