@Test
  public void testRotateFailed() throws Exception {
    when(indices.getIndexStats("name")).thenReturn(null);
    when(deflector.getNewestTargetName()).thenReturn("name");
    when(clusterConfigService.get(SizeBasedRotationStrategyConfig.class))
        .thenReturn(SizeBasedRotationStrategyConfig.create(100));

    final SizeBasedRotationStrategy strategy =
        new SizeBasedRotationStrategy(
            indices, deflector, clusterConfigService, nodeId, auditEventSender);

    strategy.rotate();
    verify(deflector, never()).cycle();
    reset(deflector);
  }
  @Nullable
  @Override
  protected Result shouldRotate(final String index) {
    final SizeBasedRotationStrategyConfig config =
        clusterConfigService.get(SizeBasedRotationStrategyConfig.class);

    if (config == null) {
      LOG.warn("No rotation strategy configuration found, not running index rotation!");
      return null;
    }

    final IndexStatistics indexStats = indices.getIndexStats(index);
    if (indexStats == null) {
      return null;
    }

    final long sizeInBytes = indexStats.primaries().getStore().getSizeInBytes();

    final boolean shouldRotate = sizeInBytes > config.maxSize();

    return new Result() {
      public final MessageFormat ROTATE =
          new MessageFormat(
              "Storage size for index <{0}> is {1} bytes, exceeding the maximum of {2} bytes. Rotating index.",
              Locale.ENGLISH);
      public final MessageFormat NOT_ROTATE =
          new MessageFormat(
              "Storage size for index <{0}> is {1} bytes, below the maximum of {2} bytes. Not doing anything.",
              Locale.ENGLISH);

      @Override
      public String getDescription() {
        MessageFormat format = shouldRotate() ? ROTATE : NOT_ROTATE;
        return format.format(new Object[] {index, sizeInBytes, config.maxSize()});
      }

      @Override
      public boolean shouldRotate() {
        return shouldRotate;
      }
    };
  }
  @Test
  public void testDontRotate() throws Exception {
    final CommonStats commonStats = new CommonStats();
    commonStats.store = new StoreStats(1000, 0);
    final IndexStatistics stats =
        IndexStatistics.create(
            "name", commonStats, commonStats, Collections.<ShardRouting>emptyList());

    when(indices.getIndexStats("name")).thenReturn(stats);
    when(deflector.getNewestTargetName()).thenReturn("name");
    when(clusterConfigService.get(SizeBasedRotationStrategyConfig.class))
        .thenReturn(SizeBasedRotationStrategyConfig.create(100000L));

    final SizeBasedRotationStrategy strategy =
        new SizeBasedRotationStrategy(
            indices, deflector, clusterConfigService, nodeId, auditEventSender);

    strategy.rotate();
    verify(deflector, never()).cycle();
    reset(deflector);
  }
  @Override
  public void doRun() {
    final ContentPackLoaderConfig contentPackLoaderConfig =
        clusterConfigService.getOrDefault(
            ContentPackLoaderConfig.class, ContentPackLoaderConfig.EMPTY);

    final List<Path> files = getFiles(contentPacksDir, FILENAME_GLOB);
    final Map<String, ConfigurationBundle> contentPacks = new HashMap<>(files.size());

    final Set<String> loadedContentPacks =
        new HashSet<>(contentPackLoaderConfig.loadedContentPacks());
    final Set<String> appliedContentPacks =
        new HashSet<>(contentPackLoaderConfig.appliedContentPacks());
    final Map<String, String> checksums = new HashMap<>(contentPackLoaderConfig.checksums());

    for (Path file : files) {
      final String fileName = file.getFileName().toString();

      LOG.debug("Reading content pack from {}", file);
      final byte[] bytes;
      try {
        bytes = Files.readAllBytes(file);
      } catch (IOException e) {
        LOG.warn("Couldn't read " + file + ". Skipping.", e);
        continue;
      }

      final String encodedFileName = encodeFileNameForMongo(fileName);
      final String checksum = HASH_FUNCTION.hashBytes(bytes).toString();
      final String storedChecksum = checksums.get(encodedFileName);
      if (storedChecksum == null) {
        checksums.put(encodedFileName, checksum);
      } else if (!checksum.equals(storedChecksum)) {
        LOG.info(
            "Checksum of {} changed (expected: {}, actual: {})", file, storedChecksum, checksum);
        continue;
      }

      if (contentPackLoaderConfig.loadedContentPacks().contains(fileName)) {
        LOG.debug("Skipping already loaded content pack {} (SHA-256: {})", file, storedChecksum);
        continue;
      }

      LOG.debug("Parsing content pack from {}", file);
      final ConfigurationBundle contentPack;
      try {
        contentPack = objectMapper.readValue(bytes, ConfigurationBundle.class);
      } catch (IOException e) {
        LOG.warn("Couldn't parse content pack in file " + file + ". Skipping", e);
        continue;
      }

      final ConfigurationBundle existingContentPack =
          bundleService.findByNameAndCategory(contentPack.getName(), contentPack.getCategory());
      if (existingContentPack != null) {
        LOG.debug(
            "Content pack {}/{} already exists in database. Skipping.",
            contentPack.getCategory(),
            contentPack.getName());
        contentPacks.put(fileName, existingContentPack);
        continue;
      }

      final ConfigurationBundle insertedContentPack;
      try {
        insertedContentPack = bundleService.insert(contentPack);
        LOG.debug(
            "Successfully inserted content pack {} into database with ID {}",
            file,
            insertedContentPack.getId());
      } catch (MongoException e) {
        LOG.error("Error while inserting content pack " + file + " into database. Skipping.", e);
        continue;
      }

      contentPacks.put(fileName, insertedContentPack);
      loadedContentPacks.add(fileName);
    }

    LOG.debug("Applying selected content packs");
    for (Map.Entry<String, ConfigurationBundle> entry : contentPacks.entrySet()) {
      final String fileName = entry.getKey();
      final ConfigurationBundle contentPack = entry.getValue();

      if (contentPacksAutoLoad.contains(fileName) && appliedContentPacks.contains(fileName)) {
        LOG.debug(
            "Content pack {}/{} ({}) already applied. Skipping.",
            contentPack.getName(),
            contentPack.getCategory(),
            fileName);
        continue;
      }

      if (contentPacksAutoLoad.contains(fileName)) {
        LOG.debug(
            "Applying content pack {}/{} ({})",
            contentPack.getName(),
            contentPack.getCategory(),
            fileName);
        bundleService.applyConfigurationBundle(contentPack, userService.getAdminUser());
        appliedContentPacks.add(fileName);
      }
    }

    final ContentPackLoaderConfig changedContentPackLoaderConfig =
        ContentPackLoaderConfig.create(loadedContentPacks, appliedContentPacks, checksums);
    if (!contentPackLoaderConfig.equals(changedContentPackLoaderConfig)) {
      clusterConfigService.write(changedContentPackLoaderConfig);
    }
  }