|  | @@ -0,0 +1,217 @@
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 | 
	
		
			
				|  |  | + * or more contributor license agreements. Licensed under the Elastic License;
 | 
	
		
			
				|  |  | + * you may not use this file except in compliance with the Elastic License.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +package org.elasticsearch.xpack.monitoring.collector.ccr;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import org.elasticsearch.action.ActionFuture;
 | 
	
		
			
				|  |  | +import org.elasticsearch.common.Strings;
 | 
	
		
			
				|  |  | +import org.elasticsearch.common.settings.Settings;
 | 
	
		
			
				|  |  | +import org.elasticsearch.common.unit.TimeValue;
 | 
	
		
			
				|  |  | +import org.elasticsearch.common.util.concurrent.ThreadContext;
 | 
	
		
			
				|  |  | +import org.elasticsearch.xpack.core.XPackSettings;
 | 
	
		
			
				|  |  | +import org.elasticsearch.xpack.core.ccr.ShardFollowNodeTaskStatus;
 | 
	
		
			
				|  |  | +import org.elasticsearch.xpack.core.ccr.action.CcrStatsAction;
 | 
	
		
			
				|  |  | +import org.elasticsearch.xpack.core.ccr.client.CcrClient;
 | 
	
		
			
				|  |  | +import org.elasticsearch.xpack.core.monitoring.MonitoredSystem;
 | 
	
		
			
				|  |  | +import org.elasticsearch.xpack.core.monitoring.exporter.MonitoringDoc;
 | 
	
		
			
				|  |  | +import org.elasticsearch.xpack.monitoring.BaseCollectorTestCase;
 | 
	
		
			
				|  |  | +import org.mockito.ArgumentMatcher;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import java.util.ArrayList;
 | 
	
		
			
				|  |  | +import java.util.Arrays;
 | 
	
		
			
				|  |  | +import java.util.Collection;
 | 
	
		
			
				|  |  | +import java.util.Iterator;
 | 
	
		
			
				|  |  | +import java.util.List;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import static java.util.Collections.emptyList;
 | 
	
		
			
				|  |  | +import static org.elasticsearch.xpack.monitoring.MonitoringTestUtils.randomMonitoringNode;
 | 
	
		
			
				|  |  | +import static org.hamcrest.Matchers.equalTo;
 | 
	
		
			
				|  |  | +import static org.hamcrest.Matchers.greaterThan;
 | 
	
		
			
				|  |  | +import static org.hamcrest.Matchers.hasSize;
 | 
	
		
			
				|  |  | +import static org.hamcrest.Matchers.is;
 | 
	
		
			
				|  |  | +import static org.hamcrest.Matchers.nullValue;
 | 
	
		
			
				|  |  | +import static org.mockito.Matchers.argThat;
 | 
	
		
			
				|  |  | +import static org.mockito.Mockito.mock;
 | 
	
		
			
				|  |  | +import static org.mockito.Mockito.verify;
 | 
	
		
			
				|  |  | +import static org.mockito.Mockito.when;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +public class CcrStatsCollectorTests extends BaseCollectorTestCase {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void testShouldCollectReturnsFalseIfMonitoringNotAllowed() {
 | 
	
		
			
				|  |  | +        final Settings settings = randomFrom(ccrEnabledSettings(), ccrDisabledSettings());
 | 
	
		
			
				|  |  | +        final boolean ccrAllowed = randomBoolean();
 | 
	
		
			
				|  |  | +        final boolean isElectedMaster = randomBoolean();
 | 
	
		
			
				|  |  | +        whenLocalNodeElectedMaster(isElectedMaster);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // this controls the blockage
 | 
	
		
			
				|  |  | +        when(licenseState.isMonitoringAllowed()).thenReturn(false);
 | 
	
		
			
				|  |  | +        when(licenseState.isCcrAllowed()).thenReturn(ccrAllowed);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final CcrStatsCollector collector = new CcrStatsCollector(settings, clusterService, licenseState, client);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assertThat(collector.shouldCollect(isElectedMaster), is(false));
 | 
	
		
			
				|  |  | +        if (isElectedMaster) {
 | 
	
		
			
				|  |  | +            verify(licenseState).isMonitoringAllowed();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void testShouldCollectReturnsFalseIfNotMaster() {
 | 
	
		
			
				|  |  | +        // regardless of CCR being enabled
 | 
	
		
			
				|  |  | +        final Settings settings = randomFrom(ccrEnabledSettings(), ccrDisabledSettings());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        when(licenseState.isMonitoringAllowed()).thenReturn(randomBoolean());
 | 
	
		
			
				|  |  | +        when(licenseState.isCcrAllowed()).thenReturn(randomBoolean());
 | 
	
		
			
				|  |  | +        // this controls the blockage
 | 
	
		
			
				|  |  | +        final boolean isElectedMaster = false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final CcrStatsCollector collector = new CcrStatsCollector(settings, clusterService, licenseState, client);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assertThat(collector.shouldCollect(isElectedMaster), is(false));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void testShouldCollectReturnsFalseIfCCRIsDisabled() {
 | 
	
		
			
				|  |  | +        // this is controls the blockage
 | 
	
		
			
				|  |  | +        final Settings settings = ccrDisabledSettings();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        when(licenseState.isMonitoringAllowed()).thenReturn(randomBoolean());
 | 
	
		
			
				|  |  | +        when(licenseState.isCcrAllowed()).thenReturn(randomBoolean());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final boolean isElectedMaster = randomBoolean();
 | 
	
		
			
				|  |  | +        whenLocalNodeElectedMaster(isElectedMaster);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final CcrStatsCollector collector = new CcrStatsCollector(settings, clusterService, licenseState, client);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assertThat(collector.shouldCollect(isElectedMaster), is(false));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (isElectedMaster) {
 | 
	
		
			
				|  |  | +            verify(licenseState).isMonitoringAllowed();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void testShouldCollectReturnsFalseIfCCRIsNotAllowed() {
 | 
	
		
			
				|  |  | +        final Settings settings = randomFrom(ccrEnabledSettings(), ccrDisabledSettings());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        when(licenseState.isMonitoringAllowed()).thenReturn(randomBoolean());
 | 
	
		
			
				|  |  | +        // this is controls the blockage
 | 
	
		
			
				|  |  | +        when(licenseState.isCcrAllowed()).thenReturn(false);
 | 
	
		
			
				|  |  | +        final boolean isElectedMaster = randomBoolean();
 | 
	
		
			
				|  |  | +        whenLocalNodeElectedMaster(isElectedMaster);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final CcrStatsCollector collector = new CcrStatsCollector(settings, clusterService, licenseState, client);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assertThat(collector.shouldCollect(isElectedMaster), is(false));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (isElectedMaster) {
 | 
	
		
			
				|  |  | +            verify(licenseState).isMonitoringAllowed();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void testShouldCollectReturnsTrue() {
 | 
	
		
			
				|  |  | +        final Settings settings = ccrEnabledSettings();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        when(licenseState.isMonitoringAllowed()).thenReturn(true);
 | 
	
		
			
				|  |  | +        when(licenseState.isCcrAllowed()).thenReturn(true);
 | 
	
		
			
				|  |  | +        final boolean isElectedMaster = true;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final CcrStatsCollector collector = new CcrStatsCollector(settings, clusterService, licenseState, client);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assertThat(collector.shouldCollect(isElectedMaster), is(true));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        verify(licenseState).isMonitoringAllowed();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void testDoCollect() throws Exception {
 | 
	
		
			
				|  |  | +        final String clusterUuid = randomAlphaOfLength(5);
 | 
	
		
			
				|  |  | +        whenClusterStateWithUUID(clusterUuid);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final MonitoringDoc.Node node = randomMonitoringNode(random());
 | 
	
		
			
				|  |  | +        final CcrClient client = mock(CcrClient.class);
 | 
	
		
			
				|  |  | +        final ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final TimeValue timeout = TimeValue.timeValueSeconds(randomIntBetween(1, 120));
 | 
	
		
			
				|  |  | +        withCollectionTimeout(CcrStatsCollector.CCR_STATS_TIMEOUT, timeout);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final CcrStatsCollector collector = new CcrStatsCollector(Settings.EMPTY, clusterService, licenseState, client, threadContext);
 | 
	
		
			
				|  |  | +        assertEquals(timeout, collector.getCollectionTimeout());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final List<CcrStatsAction.StatsResponse> statuses = mockStatuses();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        @SuppressWarnings("unchecked")
 | 
	
		
			
				|  |  | +        final ActionFuture<CcrStatsAction.StatsResponses> future = (ActionFuture<CcrStatsAction.StatsResponses>)mock(ActionFuture.class);
 | 
	
		
			
				|  |  | +        final CcrStatsAction.StatsResponses responses = new CcrStatsAction.StatsResponses(emptyList(), emptyList(), statuses);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final CcrStatsAction.StatsRequest request = new CcrStatsAction.StatsRequest();
 | 
	
		
			
				|  |  | +        request.setIndices(Strings.EMPTY_ARRAY);
 | 
	
		
			
				|  |  | +        when(client.stats(statsRequestEq(request))).thenReturn(future);
 | 
	
		
			
				|  |  | +        when(future.actionGet(timeout)).thenReturn(responses);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final long interval = randomNonNegativeLong();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final Collection<MonitoringDoc> documents = collector.doCollect(node, interval, clusterState);
 | 
	
		
			
				|  |  | +        verify(clusterState).metaData();
 | 
	
		
			
				|  |  | +        verify(metaData).clusterUUID();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        assertThat(documents, hasSize(statuses.size()));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        int index = 0;
 | 
	
		
			
				|  |  | +        for (final Iterator<MonitoringDoc> it = documents.iterator(); it.hasNext(); index++) {
 | 
	
		
			
				|  |  | +            final CcrStatsMonitoringDoc document = (CcrStatsMonitoringDoc)it.next();
 | 
	
		
			
				|  |  | +            final CcrStatsAction.StatsResponse status = statuses.get(index);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            assertThat(document.getCluster(), is(clusterUuid));
 | 
	
		
			
				|  |  | +            assertThat(document.getTimestamp(), greaterThan(0L));
 | 
	
		
			
				|  |  | +            assertThat(document.getIntervalMillis(), equalTo(interval));
 | 
	
		
			
				|  |  | +            assertThat(document.getNode(), equalTo(node));
 | 
	
		
			
				|  |  | +            assertThat(document.getSystem(), is(MonitoredSystem.ES));
 | 
	
		
			
				|  |  | +            assertThat(document.getType(), is(CcrStatsMonitoringDoc.TYPE));
 | 
	
		
			
				|  |  | +            assertThat(document.getId(), nullValue());
 | 
	
		
			
				|  |  | +            assertThat(document.status(), is(status.status()));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private List<CcrStatsAction.StatsResponse> mockStatuses() {
 | 
	
		
			
				|  |  | +        final int count = randomIntBetween(1, 8);
 | 
	
		
			
				|  |  | +        final List<CcrStatsAction.StatsResponse> statuses = new ArrayList<>(count);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        for (int i = 0; i < count; ++i) {
 | 
	
		
			
				|  |  | +            CcrStatsAction.StatsResponse statsResponse = mock(CcrStatsAction.StatsResponse.class);
 | 
	
		
			
				|  |  | +            ShardFollowNodeTaskStatus status = mock(ShardFollowNodeTaskStatus.class);
 | 
	
		
			
				|  |  | +            when(statsResponse.status()).thenReturn(status);
 | 
	
		
			
				|  |  | +            statuses.add(statsResponse);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return statuses;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private Settings ccrEnabledSettings() {
 | 
	
		
			
				|  |  | +        // since it's the default, we want to ensure we test both with/without it
 | 
	
		
			
				|  |  | +        return randomBoolean() ? Settings.EMPTY : Settings.builder().put(XPackSettings.CCR_ENABLED_SETTING.getKey(), true).build();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private Settings ccrDisabledSettings() {
 | 
	
		
			
				|  |  | +        return Settings.builder().put(XPackSettings.CCR_ENABLED_SETTING.getKey(), false).build();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private static CcrStatsAction.StatsRequest statsRequestEq(CcrStatsAction.StatsRequest expected) {
 | 
	
		
			
				|  |  | +        return argThat(new StatsRequestMatches(expected));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private static class StatsRequestMatches extends ArgumentMatcher<CcrStatsAction.StatsRequest> {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        private final CcrStatsAction.StatsRequest expected;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        private StatsRequestMatches(CcrStatsAction.StatsRequest expected) {
 | 
	
		
			
				|  |  | +            this.expected = expected;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        @Override
 | 
	
		
			
				|  |  | +        public boolean matches(Object o) {
 | 
	
		
			
				|  |  | +            CcrStatsAction.StatsRequest actual = (CcrStatsAction.StatsRequest) o;
 | 
	
		
			
				|  |  | +            return Arrays.equals(expected.indices(), actual.indices());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +}
 |