Ejemplo n.º 1
0
 def _add_proxy_clause(self, certificate, proxy_clause_builder):
   target_proxy_name = '%s-target-%s-proxy'
   if certificate:
     target_proxy_name = target_proxy_name % (self.__lb_name, 'https')
     (proxy_clause_builder.list_resource('targetHttpsProxies')
      .contains_pred_list([jp.PathEqPredicate('name', target_proxy_name)]))
   else:
     target_proxy_name = target_proxy_name % (self.__lb_name, 'http')
     (proxy_clause_builder.list_resource('targetHttpProxies')
      .contains_pred_list([jp.PathEqPredicate('name', target_proxy_name)]))
Ejemplo n.º 2
0
    def test_object_observation_verifier_with_conditional(self):
        # We need strict True here because we want each object to pass
        # the constraint test. Otherwise, if any object passes, then the whole
        # observation would pass. This causes a problem when we say that
        # we dont ever want to see 'name' unless it has a particular 'value'.
        # Without strict test, we'd allow this to occur as long as another object
        # satisfied that constraint.
        # When we use 'excludes', it applies to the whole observation since this
        # is normally the intent. However, here we are excluding values under
        # certain context -- "If the 'name' field is 'NAME' then it must contain
        # a value field 'VALUE'". Excluding name='NAME' everywhere would
        # not permit the context where value='VALUE' which we want to permit.
        verifier_builder = jc.ValueObservationVerifierBuilder(
            title='Test Conditional', strict=True)

        name_eq_pred = jp.PathEqPredicate('name', 'NAME')
        value_eq_pred = jp.PathEqPredicate('value', 'VALUE')

        conditional = jp.IF(name_eq_pred, value_eq_pred)
        pred_list = [jp.PathPredicate('', conditional)]

        verifier_builder.add_constraint(conditional)

        match_name_value_obj = {'name': 'NAME', 'value': 'VALUE'}
        match_value_not_name_obj = {'name': 'GOOD', 'value': 'VALUE'}
        match_neither_obj = {'name': 'GOOD', 'value': 'GOOD'}
        match_name_not_value_obj = {'name': 'NAME', 'value': 'BAD'}  # bad

        test_cases = [(True, [match_name_value_obj, match_neither_obj]),
                      (True, [match_value_not_name_obj, match_neither_obj]),
                      (False, [match_neither_obj, match_name_not_value_obj])]

        context = ExecutionContext()
        verifier = verifier_builder.build()
        for test in test_cases:
            observation = jc.Observation()
            result_builder = jc.ObservationVerifyResultBuilder(observation)

            expect_valid = test[0]
            obj_list = test[1]
            observation.add_all_objects(obj_list)

            result_builder.add_observation_predicate_result(
                jc.ObservationValuePredicate(conditional)(context,
                                                          observation))

            # All of these tests succeed.
            verify_results = result_builder.build(expect_valid)
            try:
                self._try_verify(context, verifier, observation, expect_valid,
                                 verify_results)
            except:
                print 'testing {0}'.format(obj_list)
                raise
Ejemplo n.º 3
0
    def test_observation_strict_vs_nonstrict(self):
        aA = jp.PathEqPredicate('a', 'A')
        bB = jp.PathEqPredicate('b', 'B')

        unstrict_object_list = [_NUMBER_DICT, _LETTER_DICT, _MIXED_DICT]
        unstrict_observation = jc.Observation()
        unstrict_observation.add_all_objects(unstrict_object_list)

        strict_object_list = [_LETTER_DICT, {'a': 'A', 'b': 'B', 'x': 'X'}]
        strict_observation = jc.Observation()
        strict_observation.add_all_objects(strict_object_list)

        none_object_list = [_NUMBER_DICT, _MIXED_DICT]
        none_observation = jc.Observation()
        none_observation.add_all_objects(none_object_list)

        # pylint: disable=bad-whitespace
        test_cases = [
            #  Name      jc.Observation        Strict,  Unstrict
            #---------------------------------------------------
            ('Strict', strict_observation, True, True),
            ('Unstrict', unstrict_observation, False, True),
            ('None', none_observation, False, False)
        ]

        # For each of the cases, test it with strict and non-strict verification.
        context = ExecutionContext()
        for test in test_cases:
            name = test[0]
            observation = test[1]

            # For this case, check it strict (2) and unstrict (3).
            for index in [2, 3]:
                test_strict = index == 2
                expected = test[index]
                verifier = jc.ValueObservationVerifier(title='Verifier',
                                                       constraints=[aA, bB],
                                                       strict=test_strict)

                verify_result = verifier(context, observation)
                try:
                    self.assertEqual(expected, verify_result.__nonzero__())
                except Exception as e:
                    print '*** FAILED case={0}:\n{1}'.format(name, e)
                    print 'GOT {0}'.format(verify_result)
                    raise
Ejemplo n.º 4
0
 def test_path_value_found_top(self):
     source = _COMPOSITE_DICT
     pred = jp.PathEqPredicate('letters', _LETTER_DICT)
     result = pred(source)
     expect = _make_result(pred, jp.DICT_EQ(_LETTER_DICT), source,
                           [PathValue('letters', _LETTER_DICT)], [])
     self.assertTrue(result)
     self.assertEqual(expect, result)
Ejemplo n.º 5
0
    def test_path_value_found_nested(self):
        source = _COMPOSITE_DICT
        pred = jp.PathEqPredicate(PATH_SEP.join(['letters', 'a']), 'A')
        result = pred(source)

        self.assertEqual(
            _make_result(pred, jp.STR_EQ('A'), source,
                         [PathValue(PATH_SEP.join(['letters', 'a']), 'A')],
                         []), result)
        self.assertTrue(result)
Ejemplo n.º 6
0
    def test_object_observer_map(self):
        # Test no filter.
        context = ExecutionContext()
        observer = jc.ObjectObserver()
        observation = jc.Observation()
        expected = jc.Observation()
        expected.add_object(_NUMBER_DICT)
        observer.filter_all_objects_to_observation(context, [_NUMBER_DICT],
                                                   observation)
        self.assertEqual([_NUMBER_DICT], observation.objects)
        self.assertEqual(expected, observation)

        pred_list = [
            jp.PathEqPredicate('a', 'A'),
            jp.PathEqPredicate('b', 'B')
        ]
        conjunction = jp.AND(pred_list)
        observer = jc.ObjectObserver(conjunction)
        observation = jc.Observation()

        expected = jc.Observation()
        expected.add_object(_LETTER_DICT)
        observer.filter_all_objects_to_observation(context, [_LETTER_DICT],
                                                   observation)
        self.assertEqual([_LETTER_DICT], observation.objects)
        self.assertEqual(expected, observation)

        observation = jc.Observation()
        expected = jc.Observation()
        expected.add_object(_LETTER_DICT)
        expected.add_object(_LETTER_DICT)
        observer.filter_all_objects_to_observation(
            context, [_LETTER_DICT, _NUMBER_DICT, _LETTER_DICT], observation)
        self.assertEqual([_LETTER_DICT, _LETTER_DICT], observation.objects)

        observation = jc.Observation()
        expected = jc.Observation()
        observer.filter_all_objects_to_observation(context, [_NUMBER_DICT],
                                                   observation)
        self.assertEqual([], observation.objects)
        # Note that filtering doesnt observe errors.
        self.assertEqual(expected, observation)
Ejemplo n.º 7
0
 def test_path_value_not_found(self):
     source = _COMPOSITE_DICT
     pred = jp.PathEqPredicate(PATH_SEP.join(['letters', 'a']), 'B')
     result = pred(source)
     self.assertEqual(
         _make_result(pred, jp.STR_EQ('B'), source, [], [
             jp.PathValueResult(pred=jp.STR_EQ('B'),
                                path_value=PathValue(
                                    PATH_SEP.join(['letters', 'a']), 'A'),
                                source=_COMPOSITE_DICT,
                                target_path=PATH_SEP.join(['letters', 'a']))
         ]), result)
Ejemplo n.º 8
0
    def terminate_instances(self, names, zone):
        """Creates test for removing specific instances.

        Args:
          names: A list of instance names to be removed.
          zone: The zone containing the instances.

        Returns:
          st.OperationContract
        """
        builder = gcp.GcpContractBuilder(self.gcp_observer)
        clause = builder.new_clause_builder(
            "Instances Deleted", retryable_for_secs=30,
            strict=True).aggregated_list_resource("instances")
        for name in names:
            # If one of our instances still exists, it should be STOPPING.
            name_matches_pred = jp.PathContainsPredicate("name", name)
            is_stopping_pred = jp.PathEqPredicate("status", "STOPPING")

            # We want the condition to apply to all the observed objects so we'll
            # map the constraint over the observation. Otherwise, if dont map it,
            # then we'd expect the constraint to hold somewhere among the observed
            # objects, but not necessarily all of them.
            clause.AND(
                ov_factory.value_list_matches(
                    [jp.IF(name_matches_pred, is_stopping_pred)], strict=True))

        # pylint: disable=bad-continuation
        payload = self.agent.type_to_payload(
            "terminateInstances",
            {
                "instanceIds": names,
                "zone": zone,
                "credentials": self.bindings["SPINNAKER_GOOGLE_ACCOUNT"],
            },
        )

        return st.OperationContract(
            self.new_post_operation(title="terminate_instances",
                                    data=payload,
                                    path="gce/ops"),
            contract=builder.build(),
        )
Ejemplo n.º 9
0
    def register_load_balancer_instances(self):
        """Creates test registering the first two instances with a load balancer.

       Assumes that create_instances test has been run to add
       the instances. Note by design these were in two different zones
       but same region as required by the API this is testing.

       Assumes that upsert_load_balancer has been run to
       create the load balancer itself.
    Returns:
      st.OperationContract
    """
        # pylint: disable=bad-continuation
        payload = self.agent.type_to_payload(
            'registerInstancesWithGoogleLoadBalancerDescription', {
                'loadBalancerNames': [self.__use_lb_name],
                'instanceIds': self.use_instance_names[:2],
                'region': self.bindings['TEST_GCE_REGION'],
                'credentials': self.bindings['GCE_CREDENTIALS']
            })

        builder = gcp.GceContractBuilder(self.gce_observer)
        (builder.new_clause_builder('Instances in Target Pool',
                                    retryable_for_secs=15).
         list_resources('target-pools').contains_pred_list([
             jp.PathContainsPredicate('name', self.__use_lb_tp_name),
             jp.PathEqPredicate('region', self.bindings['TEST_GCE_REGION']),
             jp.PathElementsContainPredicate('instances',
                                             self.use_instance_names[0]),
             jp.PathElementsContainPredicate('instances',
                                             self.use_instance_names[1])
         ]).excludes_pred_list([
             jp.PathContainsPredicate('name', self.__use_lb_tp_name),
             jp.PathElementsContainPredicate('instances',
                                             self.use_instance_names[2])
         ]))

        return st.OperationContract(
            self.new_post_operation(title='register_load_balancer_instances',
                                    data=payload,
                                    path='ops'),
            contract=builder.build())
Ejemplo n.º 10
0
  def terminate_instances(self, names, zone):
    """Creates test for removing specific instances.

    Args:
      names: A list of instance names to be removed.
      zone: The zone containing the instances.

    Returns:
      st.OperationContract
    """
    builder = gcp.GcpContractBuilder(self.gcp_observer)
    clause = (builder.new_clause_builder('Instances Deleted',
                                         retryable_for_secs=15,
                                         strict=True)
              .aggregated_list_resource('instances'))
    for name in names:
      # If one of our instances still exists, it should be STOPPING.
      name_matches_pred = jp.PathContainsPredicate('name', name)
      is_stopping_pred = jp.PathEqPredicate('status', 'STOPPING')

      # We want the condition to apply to all the observed objects so we'll
      # map the constraint over the observation. Otherwise, if dont map it,
      # then we'd expect the constraint to hold somewhere among the observed
      # objects, but not necessarily all of them.
      clause.add_constraint(jp.IF(name_matches_pred, is_stopping_pred))

    # pylint: disable=bad-continuation
    payload = self.agent.type_to_payload(
          'terminateInstances',
          {
            'instanceIds': names,
            'zone': zone,
            'credentials': self.bindings['SPINNAKER_GOOGLE_ACCOUNT']
          })

    return st.OperationContract(
        self.new_post_operation(
            title='terminate_instances', data=payload, path='gce/ops'),
        contract=builder.build())
Ejemplo n.º 11
0
  def _add_contract_clauses(self, contract_builder, upsert):
    '''Add the proper predicates to the contract builder for a given
    upsert description.
    '''
    host_rules = upsert['hostRules'] # Host rules will be distinct.
    backend_services = [upsert['defaultService']]
    for host_rule in host_rules:
      path_matcher = host_rule['pathMatcher']
      backend_services.append(path_matcher['defaultService'])
      for path_rule in path_matcher['pathRules']:
        backend_services.append(path_rule['backendService'])
    health_checks = [service['healthCheck'] for service in backend_services]

    hc_clause_builder = (contract_builder
                         .new_clause_builder('Health Checks Created',
                                             retryable_for_secs=30)
                         .list_resource('httpHealthChecks'))
    for hc in health_checks:
      hc_clause_builder.contains_pred_list(
        [
          jp.PathEqPredicate('name', hc['name']),
          jp.PathEqPredicate('requestPath', hc['requestPath']),
          jp.PathEqPredicate('port', hc['port'])
        ]
      )

    bs_clause_builder = (contract_builder.
                         new_clause_builder('Backend Services Created',
                                            retryable_for_secs=30).
                         list_resource('backendServices'))
    for bs in backend_services:
      bs_clause_builder.contains_pred_list(
        [
         jp.PathEqPredicate('name', bs['name']),
         jp.PathEqPredicate('portName', 'http'),
         jp.PathContainsPredicate('healthChecks[0]',
                                  self._get_hc_link(bs['healthCheck']['name']))
        ]
      )

    url_map_clause_builder = (contract_builder
                              .new_clause_builder('Url Map Created',
                                                  retryable_for_secs=30)
                              .list_resource('urlMaps'))
    for hr in host_rules:
      pred_list = []
      pm = hr['pathMatcher']
      pred_list.append(jp.AND([
        jp.PathEqPredicate('name', self.__lb_name),
        jp.PathEqPredicate('defaultService',
                           self._get_bs_link(upsert['defaultService']['name'])),
        jp.PathContainsPredicate(
          'pathMatchers/defaultService',
          self._get_bs_link(pm['defaultService']['name'])),
      ]))
      pred_list.append(
        jp.AND([jp.PathContainsPredicate('hostRules/hosts',
                                         host) for host in hr['hostPatterns']])
      )
      for pr in pm['pathRules']:
        pred_list.append(
         jp.PathContainsPredicate(
           'pathMatchers/pathRules/service',
           self._get_bs_link(pr['backendService']['name'])),
        )
        for path in pr['paths']:
          pred_list.append(
            jp.PathContainsPredicate('pathMatchers/pathRules/paths', path),
          )
      url_map_clause_builder.contains_pred_list(pred_list)

    port_string = '443-443'
    if upsert['certificate'] == '':
      port_string = '%s-%s' % (upsert['portRange'], upsert['portRange'])

    (contract_builder.new_clause_builder('Forwarding Rule Created',
                                         retryable_for_secs=30)
     .list_resource('globalForwardingRules')
     .contains_pred_list(
       [
         jp.PathEqPredicate('name', self.__lb_name),
         jp.PathEqPredicate('portRange', port_string)
       ]))

    proxy_clause_builder = contract_builder.new_clause_builder(
      'Target Proxy Created', retryable_for_secs=30)
    self._add_proxy_clause(upsert['certificate'], proxy_clause_builder)