Example #1
0
 def create_update_settings(cls):
     return JobUpdateSettings(updateGroupSize=1,
                              maxPerInstanceFailures=2,
                              maxFailedInstances=1,
                              minWaitInInstanceRunningMs=50 * 1000,
                              rollbackOnFailure=True,
                              waitForBatchCompletion=False)
Example #2
0
 def create_update_settings(cls):
     return JobUpdateSettings(updateGroupSize=1,
                              maxPerInstanceFailures=2,
                              maxFailedInstances=1,
                              maxWaitToInstanceRunningMs=50 * 1000,
                              minWaitInInstanceRunningMs=50 * 1000,
                              rollbackOnFailure=True)
Example #3
0
 def create_update_settings(cls):
     return JobUpdateSettings(
         updateGroupSize=1,
         updateStrategy=JobUpdateStrategy(
             queueStrategy=QueueJobUpdateStrategy(groupSize=1),
             batchStrategy=None,
             varBatchStrategy=None),
         maxPerInstanceFailures=2,
         maxFailedInstances=1,
         minWaitInInstanceRunningMs=50 * 1000,
         rollbackOnFailure=True,
         waitForBatchCompletion=False,
         slaAware=False)
Example #4
0
    def to_thrift_update_settings(self, instances=None):
        """Converts UpdateConfig into thrift JobUpdateSettings object.

    Arguments:
    instances - optional list of instances to update.
    """
        return JobUpdateSettings(
            updateGroupSize=self.batch_size,
            maxPerInstanceFailures=self.max_per_instance_failures,
            maxFailedInstances=self.max_total_failures,
            maxWaitToInstanceRunningMs=self.restart_threshold,
            minWaitInInstanceRunningMs=self.watch_secs,
            rollbackOnFailure=self.rollback_on_failure,
            updateOnlyTheseInstances=self.instances_to_ranges(instances)
            if instances else None)
Example #5
0
    def to_thrift_update_settings(self, instances=None):
        """Converts UpdateConfig into thrift JobUpdateSettings object.

    Arguments:
    instances - optional list of instances to update.
    """
        return JobUpdateSettings(
            updateGroupSize=self.batch_size,
            maxPerInstanceFailures=self.max_per_instance_failures,
            maxFailedInstances=self.max_total_failures,
            minWaitInInstanceRunningMs=self.watch_secs * 1000,
            rollbackOnFailure=self.rollback_on_failure,
            waitForBatchCompletion=self.wait_for_batch_completion,
            updateOnlyTheseInstances=self.instances_to_ranges(instances)
            if instances else None,
            blockIfNoPulsesAfterMs=self.pulse_interval_secs *
            1000 if self.pulse_interval_secs else None)
Example #6
0
    def to_thrift_update_settings(self, instances=None):
        """Converts UpdateConfig into thrift JobUpdateSettings object.

    Arguments:
    instances - optional list of instances to update.
    """

        if self.update_strategy is Empty:
            update_strategy = Choice([
                PystachioQueueUpdateStrategy, PystachioBatchUpdateStrategy,
                PystachioVariableBatchUpdateStrategy
            ])
            if self.wait_for_batch_completion:
                self.update_strategy = update_strategy(
                    PystachioBatchUpdateStrategy(batch_size=self.batch_size))
            else:
                self.update_strategy = update_strategy(
                    PystachioQueueUpdateStrategy(batch_size=self.batch_size))
        else:
            unwrapped = self.update_strategy.unwrap()
            if isinstance(unwrapped, PystachioQueueUpdateStrategy):
                self.batch_size = self.update_strategy.groupSize
            elif isinstance(unwrapped, PystachioBatchUpdateStrategy):
                self.batch_size = self.update_strategy.groupSize
                self.wait_for_batch_completion = True
            elif isinstance(unwrapped, PystachioBatchUpdateStrategy):
                self.batch_size = self.update_strategy.groupSizes[0]

        return JobUpdateSettings(
            updateGroupSize=self.batch_size,
            maxPerInstanceFailures=self.max_per_instance_failures,
            maxFailedInstances=self.max_total_failures,
            minWaitInInstanceRunningMs=self.watch_secs * 1000,
            rollbackOnFailure=self.rollback_on_failure,
            waitForBatchCompletion=self.wait_for_batch_completion,
            updateOnlyTheseInstances=self.instances_to_ranges(instances)
            if instances else None,
            updateStrategy=create_update_strategy_config(self.update_strategy),
            blockIfNoPulsesAfterMs=(self.pulse_interval_secs * 1000
                                    if self.pulse_interval_secs else None),
            slaAware=self.sla_aware)
class TestUpdaterUtil(unittest.TestCase):

    EXPECTED_JOB_UPDATE_SETTINGS = JobUpdateSettings(
        blockIfNoPulsesAfterMs=None,
        updateOnlyTheseInstances=None,
        slaAware=False,
        maxPerInstanceFailures=0,
        waitForBatchCompletion=False,
        rollbackOnFailure=True,
        minWaitInInstanceRunningMs=45000,
        updateGroupSize=1,
        maxFailedInstances=0)

    UPDATE_STRATEGIES = Choice([
        PystachioQueueUpdateStrategy, PystachioBatchUpdateStrategy,
        PystachioVariableBatchUpdateStrategy
    ])

    def test_multiple_ranges(self):
        """Test multiple ranges."""
        ranges = [
            repr(e)
            for e in UpdaterConfig.instances_to_ranges([1, 2, 3, 5, 7, 8])
        ]
        assert 3 == len(ranges), "Wrong number of ranges:%s" % len(ranges)
        assert repr(Range(first=1, last=3)) in ranges, "Missing range [1,3]"
        assert repr(Range(first=5, last=5)) in ranges, "Missing range [5,5]"
        assert repr(Range(first=7, last=8)) in ranges, "Missing range [7,8]"

    def test_one_element(self):
        """Test one ID in the list."""
        ranges = [repr(e) for e in UpdaterConfig.instances_to_ranges([1])]
        assert 1 == len(ranges), "Wrong number of ranges:%s" % len(ranges)
        assert repr(Range(first=1, last=1)) in ranges, "Missing range [1,1]"

    def test_none_list(self):
        """Test None list produces None result."""
        assert UpdaterConfig.instances_to_ranges(
            None) is None, "Result must be None."

    def test_empty_list(self):
        """Test empty list produces None result."""
        assert UpdaterConfig.instances_to_ranges(
            []) is None, "Result must be None."

    def test_pulse_interval_secs(self):
        config = UpdaterConfig(
            UpdateConfig(batch_size=1,
                         watch_secs=1,
                         max_per_shard_failures=1,
                         max_total_failures=1,
                         pulse_interval_secs=60))
        assert 60000 == config.to_thrift_update_settings(
        ).blockIfNoPulsesAfterMs

    def test_pulse_interval_unset(self):
        config = UpdaterConfig(
            UpdateConfig(batch_size=1,
                         watch_secs=1,
                         max_per_shard_failures=1,
                         max_total_failures=1))
        assert config.to_thrift_update_settings(
        ).blockIfNoPulsesAfterMs is None

    def test_pulse_interval_too_low(self):
        threshold = UpdaterConfig.MIN_PULSE_INTERVAL_SECONDS
        with raises(ValueError) as e:
            UpdaterConfig(
                UpdateConfig(batch_size=1,
                             watch_secs=1,
                             max_per_shard_failures=1,
                             max_total_failures=1,
                             pulse_interval_secs=threshold - 1))
        assert 'Pulse interval seconds must be at least %s seconds.' % threshold in e.value.message

    def test_to_thrift_update_settings_strategy(self):
        """Test to_thrift produces an expected thrift update settings configuration
       from a Pystachio update object.
    """

        config = UpdaterConfig(
            UpdateConfig(update_strategy=self.UPDATE_STRATEGIES(
                PystachioVariableBatchUpdateStrategy(
                    batch_sizes=[1, 2, 3, 4], autopause_after_batch=True))))

        thrift_update_config = config.to_thrift_update_settings()

        update_settings = copy.deepcopy(self.EXPECTED_JOB_UPDATE_SETTINGS)

        update_settings.updateStrategy = JobUpdateStrategy(
            batchStrategy=None,
            queueStrategy=None,
            varBatchStrategy=VariableBatchJobUpdateStrategy(
                groupSizes=(1, 2, 3, 4), autopauseAfterBatch=True))

        assert thrift_update_config == update_settings

    def test_to_thrift_update_settings_no_strategy_queue(self):
        """Test to_thrift produces an expected thrift update settings configuration
       from a Pystachio update object that doesn't include an update strategy.

       The configuration in this test should be converted to a
       QueueJobUpdateStrategy.
    """

        config = UpdaterConfig(UpdateConfig())

        thrift_update_config = config.to_thrift_update_settings()

        update_settings = copy.deepcopy(self.EXPECTED_JOB_UPDATE_SETTINGS)
        update_settings.updateStrategy = JobUpdateStrategy(
            batchStrategy=None,
            queueStrategy=QueueJobUpdateStrategy(groupSize=1),
            varBatchStrategy=None)

        assert thrift_update_config == update_settings

    def test_to_thrift_update_settings_no_strategy_batch(self):
        """Test to_thrift produces an expected thrift update settings configuration
       from a Pystachio update object that doesn't include an update strategy.

       The configuration in this test should be converted to a
       BatchJobUpdateStrategy.
    """

        config = UpdaterConfig(UpdateConfig(wait_for_batch_completion=True))

        thrift_update_config = config.to_thrift_update_settings()

        update_settings = copy.deepcopy(self.EXPECTED_JOB_UPDATE_SETTINGS)
        update_settings.updateStrategy = JobUpdateStrategy(
            batchStrategy=BatchJobUpdateStrategy(groupSize=1,
                                                 autopauseAfterBatch=False),
            queueStrategy=None,
            varBatchStrategy=None)
        update_settings.waitForBatchCompletion = True

        assert thrift_update_config == update_settings

    def test_wait_for_batch_completion_and_update_strategy(self):
        """Test setting wait_for_batch_completion along with an update strategy.
       This combination should result in a fast fail.
    """

        with raises(ValueError) as e:
            UpdaterConfig(
                UpdateConfig(wait_for_batch_completion=True,
                             update_strategy=self.UPDATE_STRATEGIES(
                                 PystachioBatchUpdateStrategy(batch_size=3))))

        assert ('Ambiguous update configuration. Cannot combine '
                'wait_batch_completion with an '
                'explicit update strategy.' in e.value.message)

    def test_batch_size_and_update_strategy(self):
        """Test setting a batch size along with an update strategy.
       This combination should result in a fast fail.
    """

        with raises(ValueError) as e:
            UpdaterConfig(
                UpdateConfig(batch_size=2,
                             update_strategy=self.UPDATE_STRATEGIES(
                                 PystachioBatchUpdateStrategy(batch_size=3))))

        assert ('Ambiguous update configuration. Cannot combine '
                'update strategy with batch size. Please set batch'
                'size inside of update strategy instead.' in e.value.message)