public static ProvisionResponse validateProvisionResponse(ProvisionResponse provisionResponse, ClusterModel clusterModel,
                                                            int overprovisionedMinBrokers) {
    if (provisionResponse.status() != ProvisionStatus.OVER_PROVISIONED) {
      return provisionResponse;
    }
    // ensure that a cluster is not identified as over provisioned unless it has the minimum required number of alive brokers
    if (clusterModel.aliveBrokers().size() < overprovisionedMinBrokers) {
      return new ProvisionResponse(ProvisionStatus.RIGHT_SIZED);
    }
    // when status is OVER_PROVISIONED goal is expected to have exactly 1 recommendation
    if (provisionResponse.recommendationByRecommender().size() != 1) {
      throw new IllegalArgumentException(String.format("Expected to have exactly 1 provision recommendation, but got: %d",
                                                       provisionResponse.recommendationByRecommender().size()));
    }
    String goalName = provisionResponse.recommendationByRecommender().keySet().iterator().next();
    int numBrokersToDrop = provisionResponse.recommendationByRecommender().values().iterator().next().numBrokers();
    // this variable indicates the maximum number of brokers that can be safely dropped.
    int maxAllowedNumBrokersToDrop = clusterModel.aliveBrokers().size() - clusterModel.maxReplicationFactor();
    if (numBrokersToDrop <= maxAllowedNumBrokersToDrop) {
      // return provision response as it is if the recommended number of brokers to drop is smaller or equal to the max allowed number of
      // brokers that can be safely dropped
      return provisionResponse;
    } else if (maxAllowedNumBrokersToDrop > 0) {
      // change the recommended number of brokers to drop if the original recommendation can not be safely satisfied
      ProvisionRecommendation recommendation =
          new ProvisionRecommendation.Builder(ProvisionStatus.OVER_PROVISIONED).numBrokers(maxAllowedNumBrokersToDrop).build();
      return new ProvisionResponse(ProvisionStatus.OVER_PROVISIONED, recommendation, goalName);
    } else {
      // change provision response status to RIGHT_SIZED if none of the brokers can be safely dropped
      return new ProvisionResponse(ProvisionStatus.RIGHT_SIZED);
    }
  }
@Test
  public void testValidateProvisionResponse() {
    // min required num of brokers > num of brokers
    ProvisionResponse response = GoalUtils.validateProvisionResponse(provisionResponse(1), clusterModel(3), 6);
    assertEquals(RIGHT_SIZED, response.status());

    // recommended num of brokers to drop is 1 and max allowed num of brokers to drop is 2, so 1 broker can be safely dropped
    response = GoalUtils.validateProvisionResponse(provisionResponse(1), clusterModel(2), 4);
    assertEquals(OVER_PROVISIONED, response.status());
    assertEquals(1, response.recommendationByRecommender().values().iterator().next().numBrokers());

    // recommended num of brokers to drop is 3 but max allowed num of brokers to drop is 1, so final provision response is to drop 1 broker
    response = GoalUtils.validateProvisionResponse(provisionResponse(3), clusterModel(3), 4);
    assertEquals(OVER_PROVISIONED, response.status());
    assertEquals(1, response.recommendationByRecommender().values().iterator().next().numBrokers());

    // recommended num of brokers to drop is 1 but max allowed num of brokers to drop is 0, so none of the brokers can be dropped
    response = GoalUtils.validateProvisionResponse(provisionResponse(1), clusterModel(4), 4);
    assertEquals(RIGHT_SIZED, response.status());
  }