Example #1
0
    def __lazy_binding_initializer(self, bindings, key):
        normalized_key = key.upper()

        ec2_client = None

        if normalized_key == 'TEST_AWS_VPC_ID':
            # We need to figure out a specific aws vpc id to use.
            logger = logging.getLogger(__name__)
            logger.info('Determine default AWS VpcId...')
            if not ec2_client:
                ec2_client = self.observer.make_boto_client('ec2')

            # If we want the name defaultvpc then do this
            # filters = [{'Name': 'tag:Name', 'Values': ['defaultvpc']}]
            # I think we want the VPC that is the default
            # filters = [{'Name': 'isDefault', 'Values': ['true']}]
            filters = [{'Name': 'tag:Name', 'Values': ['defaultvpc']}]

            response = self.observer.call_method(ExecutionContext(),
                                                 ec2_client.describe_vpcs,
                                                 Filters=filters)

            vpc_list = response['Vpcs']
            if not vpc_list:
                raise ValueError(
                    'There is no vpc matching filter {0}'.format(filters))

            found = vpc_list[0]['VpcId']
            logger.info('Using discovered default VpcId=%s', str(found))
            return found

        if normalized_key == 'TEST_AWS_SECURITY_GROUP_ID':
            # We need to figure out a specific security group that is compatable
            # with the VpcId we are using.
            logger = logging.getLogger(__name__)
            logger.info('Determine default AWS SecurityGroupId...')
            if not ec2_client:
                ec2_client = self.observer.make_boto_client('ec2')
            response = self.observer.call_method(
                ExecutionContext(), ec2_client.describe_security_groups)
            sg_list = response['SecurityGroups']

            found = None
            vpc_id = bindings['TEST_AWS_VPC_ID']
            for entry in sg_list:
                if entry.get('VpcId', None) == vpc_id:
                    found = entry['GroupId']
                    break
            if not found:
                raise ValueError(
                    'Could not find a security group for AWS_VPC_ID {0}'.
                    format(vpc_id))

            logger.info('Using discovered default SecurityGroupId=%s',
                        str(found))
            return found

        raise KeyError(key)
Example #2
0
    def __lazy_binding_initializer(self, bindings, key):
        normalized_key = key.upper()

        if normalized_key == 'TEST_AWS_VPC_ID':
            # We need to figure out a specific aws vpc id to use.
            logger = logging.getLogger(__name__)
            logger.info('Determine default AWS VpcId...')
            vpc_list = self.observer.get_resource_list(
                ExecutionContext(),
                root_key='Vpcs',
                aws_command='describe-vpcs',
                args=['--filters', 'Name=tag:Name,Values=defaultvpc'],
                region=bindings['TEST_AWS_REGION'],
                aws_module='ec2',
                profile=self.observer.profile)
            if not vpc_list:
                raise ValueError('There is no vpc tagged as "defaultvpc"')

            found = vpc_list[0]['VpcId']
            logger.info('Using discovered default VpcId=%s', str(found))
            return found

        if normalized_key == 'TEST_AWS_SECURITY_GROUP_ID':
            # We need to figure out a specific security group that is compatable
            # with the VpcId we are using.
            logger = logging.getLogger(__name__)
            logger.info('Determine default AWS SecurityGroupId...')
            sg_list = self.observer.get_resource_list(
                ExecutionContext(),
                root_key='SecurityGroups',
                aws_command='describe-security-groups',
                args=[],
                region=bindings['TEST_AWS_REGION'],
                aws_module='ec2',
                profile=self.observer.profile)

            found = None
            vpc_id = bindings['TEST_AWS_VPC_ID']
            for entry in sg_list:
                if entry.get('VpcId', None) == vpc_id:
                    found = entry['GroupId']
                    break
            if not found:
                raise ValueError(
                    'Could not find a security group for AWS_VPC_ID {0}'.
                    format(vpc_id))

            logger.info('Using discovered default SecurityGroupId=%s',
                        str(found))
            return found

        raise KeyError(key)
Example #3
0
def verify_quota(title, gcp_agent, project_quota, regions):
    """Verify that the observed GCP project has sufficient quota.

  Args:
    title: [string] What the quota is for, for logging purposes only.
    gcp_agent: [GcpAgent] Observation agent on the desired project.
    project_quota: [dict] Minimum desired values keyed by quota metric for
       the observed project.
    regions: [array of (name, dict) tuple]: A list of regions and their
       individual quotas to check.

  Returns:
    json_contract.ContractVerifyResult against the quota check.
  """
    execution_context = ExecutionContext()
    contract = make_quota_contract(gcp_agent, project_quota, regions)
    verify_results = None
    context_relation = 'ERROR'

    try:
        JournalLogger.begin_context(title)
        verify_results = contract.verify(execution_context)
        context_relation = 'VALID' if verify_results else 'INVALID'
    finally:
        if verify_results is not None:
            journal = get_global_journal()
            if journal is not None:
                journal.store(verify_results)
        JournalLogger.end_context(relation=context_relation)

    return verify_results
Example #4
0
  def test_condition_else_fail(self):
    context = ExecutionContext()
    aA = jp.PathEqPredicate('a', 'A')
    bB = jp.PathEqPredicate('b', 'B')
    cC = jp.PathEqPredicate('c', 'C')

    ifAthenBelseC = jc.IF(aA, bB, cC)

    # False if all conditions are false
    # False if "if" is true and "then" is false even if "else" matches.
    test_cases = [{'a':'A', 'b':'X', 'c':'C'},
                  {'a':'X', 'b':'B', 'c':'D'}]
    for i in range(2):
      test = test_cases[i]
      tried = [aA(context, test)]
      if i < 1:
        # First has true IF so tries THEN
        tried.append(bB(context, test))
      else:
        # Remainder has false IF so tries ELSE
        tried.append(cC(context, test))

      expect = jc.CompositePredicateResult(
          valid=False, pred=ifAthenBelseC, results=tried)
      result = ifAthenBelseC(context, test)
      self.assertFalse(result)
      self.assertEqual(expect, result)
Example #5
0
    def _do_init_bindings(self):
        """Hook to initialize custom test bindings so journaling is scoped."""
        context = ExecutionContext()
        config = self.agent.deployed_config
        # If we're running this test and dont have a config, assume it is favorable.
        enabled = config.get('spinnaker.gcs.enabled', True)
        if enabled == False:
            raise ValueError('spinnaker.gcs.enabled is not True')
        if not self.bindings['GCS_BUCKET'] and not config[
                'spinnaker.gcs.bucket']:
            raise ValueError('The GCS bucket name is not specified')
        if not self.bindings['GCS_BASE_PATH'] and not config[
                'spinnaker.gcs.rootFolder']:
            raise ValueError('The GCS rootFolder is not specified')

        self.BUCKET = self.bindings['GCS_BUCKET'] or config[
            'spinnaker.gcs.bucket']
        self.BASE_PATH = self.bindings['GCS_BASE_PATH'] or config[
            'spinnaker.gcs.rootFolder']
        self.TEST_APP = self.bindings['TEST_APP']
        self.TEST_PIPELINE_NAME = 'My {app} Pipeline'.format(app=self.TEST_APP)
        self.TEST_PIPELINE_ID = '{app}-pipeline-id'.format(app=self.TEST_APP)
        self.gcs_observer = gcp.GcpStorageAgent.make_agent(
            credentials_path=self.bindings['GCS_JSON_PATH'],
            scopes=(gcp.gcp_storage_agent.STORAGE_FULL_SCOPE
                    if self.bindings['GCS_JSON_PATH'] else None))

        metadata = self.gcs_observer.inspect_bucket(context, self.BUCKET)
        self.versioning_enabled = (metadata.get('versioning',
                                                {}).get('enabled', False))
        if not self.versioning_enabled:
            self.logger.info('bucket=%s versioning enabled=%s', self.BUCKET,
                             self.versioning_enabled)
Example #6
0
    def _do_init_bindings(self):
        """Hook to initialize custom test bindings so journaling is scoped."""
        context = ExecutionContext()
        config = self.agent.deployed_config
        # If we're running this test and dont have a config, assume it is favorable.
        enabled = config.get("spinnaker.gcs.enabled", True)
        if enabled == False:
            raise ValueError("spinnaker.gcs.enabled is not True")
        if not self.bindings["GCS_BUCKET"] and not config[
                "spinnaker.gcs.bucket"]:
            raise ValueError("The GCS bucket name is not specified")
        if (not self.bindings["GCS_BASE_PATH"]
                and not config["spinnaker.gcs.rootFolder"]):
            raise ValueError("The GCS rootFolder is not specified")

        self.BUCKET = self.bindings["GCS_BUCKET"] or config[
            "spinnaker.gcs.bucket"]
        self.BASE_PATH = (self.bindings["GCS_BASE_PATH"]
                          or config["spinnaker.gcs.rootFolder"])
        self.TEST_APP = self.bindings["TEST_APP"]
        self.TEST_PIPELINE_NAME = "My {app} Pipeline".format(app=self.TEST_APP)
        self.TEST_PIPELINE_ID = "{app}-pipeline-id".format(app=self.TEST_APP)
        self.gcs_observer = gcp.GcpStorageAgent.make_agent(
            credentials_path=self.bindings["GCS_JSON_PATH"],
            scopes=gcp.gcp_storage_agent.STORAGE_FULL_SCOPE,
        )

        metadata = self.gcs_observer.inspect_bucket(context, self.BUCKET)
        self.versioning_enabled = metadata.get("versioning",
                                               {}).get("enabled", False)
        if not self.versioning_enabled:
            self.logger.info("bucket=%s versioning enabled=%s", self.BUCKET,
                             self.versioning_enabled)
 def test_dict_specific_operator_type_mismatch(self):
     context = ExecutionContext()
     operand = {'a': 'A'}
     for value in [['a'], 'a', 1]:
         for factory in [jp.DICT_SUBSET]:
             self.simple_operand_type_mismatch_helper(
                 context, dict, factory, operand, value)
Example #8
0
    def test_collect_from_list_identity(self):
        context = ExecutionContext()
        letters = ['A', 'B', 'C']
        pred = PathPredicate('')
        values = pred(context, letters)
        self.assertEqual([
            PathValue('[0]', 'A'),
            PathValue('[1]', 'B'),
            PathValue('[2]', 'C')
        ], values.path_values)
        self.assertEqual([], values.path_failures)

        pred = PathPredicate(DONT_ENUMERATE_TERMINAL)
        values = pred(context, letters)
        self.assertEqual([PathValue('', letters)], values.path_values)
        self.assertEqual([], values.path_failures)

        pred = PathPredicate(PATH_SEP)
        values = pred(context, letters)
        self.assertEqual([
            PathValue('[0]', 'A'),
            PathValue('[1]', 'B'),
            PathValue('[2]', 'C')
        ], values.path_values)
        self.assertEqual([], values.path_failures)
  def test_obsolete_observation_failure_or_found(self):
    context = ExecutionContext()
    observation = jc.Observation()
    observation.add_error(ValueError('not the error'))

    failure_verifier = TestObsoleteObservationFailureVerifier(
        'Verify', 'NotFound')
    comment = failure_verifier._error_not_found_comment(observation)
    failure_result = jp.PredicateResult(valid=False, comment=comment)
    # We've already established this result is what we expect
    bad_observation_result = failure_verifier(context, observation)

    success_pred_result = jp.PredicateResult(valid=True)
    good_observation_result = _makeObservationVerifyResult(
      valid=True,
      good_results=[success_pred_result],
      observation=observation)
    success_verifier = FakeObservationVerifier(
          'Found', dnf_verifier=[], result=good_observation_result)

    builder = jc.ObservationVerifierBuilder(title='Observation Verifier')
    builder.EXPECT(failure_verifier).OR(success_verifier)
    verifier = builder.build()

    expect = jc.ObservationVerifyResult(
        valid=True, observation=observation,
        bad_results=bad_observation_result.bad_results,
        good_results=good_observation_result.good_results,
        failed_constraints=[])

    got = verifier(context, observation)
    self.assertEqual(expect, got)
  def test_obsolete_observation_failure_not_ok(self):
    error_text = 'the error'
    context = ExecutionContext()
    observation = jc.Observation()
    error = ValueError('not the error')
    observation.add_error(error)

    failure_verifier = TestObsoleteObservationFailureVerifier(
        'Test', error_text)
    comment = failure_verifier._error_not_found_comment(observation)
    failure_pred_result = jp.PredicateResult(valid=False, comment=comment)

    expect_failure = jc.ObservationVerifyResult(
        valid=False, observation=observation,
        bad_results=[jp.ObjectResultMapAttempt(observation,
                                               failure_pred_result)],
        good_results=[], failed_constraints=[],
        comment=comment)
    self.assertEqual(expect_failure, failure_verifier(context, observation))

    builder = jc.ObservationVerifierBuilder(title='Test Verifier')
    builder.EXPECT(failure_verifier)
    verifier = builder.build()

    expect = jc.ObservationVerifyResult(
        valid=False, observation=observation,
        bad_results=expect_failure.bad_results,
        good_results=[], failed_constraints=[])
    got = verifier(context, observation)
    self.assertEqual(expect, got)
  def test_obsolete_observation_failure_ok(self):
    error_text = 'the error'
    context = ExecutionContext()

    observation = jc.Observation()
    error = ValueError(error_text)
    observation.add_error(error)

    failure_verifier = TestObsoleteObservationFailureVerifier(
        'Test', error_text)
    failure_pred_result = jc.ObservationFailedError([error], valid=True)

    expect_failure = jc.ObservationVerifyResult(
        valid=True, observation=observation,
        good_results=[jp.ObjectResultMapAttempt(observation,
                                                failure_pred_result)],
        bad_results=[], failed_constraints=[],
        comment=_TEST_FOUND_ERROR_COMMENT)
    got = failure_verifier(context, observation)
    self.assertEqual(expect_failure, got)

    builder = jc.ObservationVerifierBuilder(title='Test')
    builder.EXPECT(failure_verifier)
    verifier = builder.build()

    expect = jc.ObservationVerifyResult(
        valid=True, observation=observation,
        good_results=expect_failure.good_results,
        bad_results=[], failed_constraints=[])

    got = verifier(context, observation)
    self.assertEqual(expect, got)
  def test_result_observation_verifier_disjunction_failure(self):
    context = ExecutionContext()
    observation = jc.Observation()
    builder = jc.ObservationVerifierBuilder(title='Test')
    verifiers = []
    results = []
    pred_results = [jp.PredicateResult(False, comment='Result %d' % i)
                                       for i in range(2)]
    for i in range(2):
      result = _makeObservationVerifyResult(observation=observation,
          valid=False, bad_results=[pred_results[i]])
      fake_verifier = FakeObservationVerifier(
          title=i, dnf_verifier=[], result=result)
      verifiers.append(fake_verifier)
      results.append(result)
      builder.OR(fake_verifier)

    verifier = builder.build()
    self.assertEqual([verifiers[0:1], verifiers[1:2]], verifier.dnf_verifiers)

    expect = _makeObservationVerifyResult(
        False, observation=observation, bad_results=pred_results)

    global _called_verifiers
    _called_verifiers = []
    got = verifier(context, observation)

    self.assertEqual(expect, got)
    self.assertEqual(verifiers, _called_verifiers)
  def test_result_observation_verifier_disjunction_success_aborts_early(self):
    context = ExecutionContext()
    builder = jc.ObservationVerifierBuilder(title='Test')
    verifiers = []
    results = []
    pred_results = [jp.PredicateResult(False, comment='Result %d' % i)
                                       for i in range(2)]
    for i in range(2):
      result = _makeObservationVerifyResult(
          valid=True, good_results=[pred_results[i]])
      fake_verifier = FakeObservationVerifier(
          title=i, dnf_verifier=[], result=result)
      verifiers.append(fake_verifier)
      results.append(result)
      builder.OR(fake_verifier)

    verifier = builder.build()
    self.assertEqual([verifiers[0:1], verifiers[1:2]], verifier.dnf_verifiers)

    expect = _makeObservationVerifyResult(True, good_results=[pred_results[0]])

    global _called_verifiers
    _called_verifiers = []
    got = verifier(context, jc.Observation())

    self.assertEqual(expect, got)
    self.assertEqual(verifiers[:1], _called_verifiers)
  def test_result_observation_verifier_conjunction_failure_aborts_early(self):
    context = ExecutionContext()
    builder = jc.ObservationVerifierBuilder(title='Test')
    verifiers = []
    results = []
    pred_results = [jp.PredicateResult(False, comment='Result %d' % i)
                                       for i in range(3)]
    for i in range(3):
      result = _makeObservationVerifyResult(
          valid=False, bad_results=[pred_results[i]])
      fake_verifier = FakeObservationVerifier(
          title=i, dnf_verifier=[], result=result)
      verifiers.append(fake_verifier)
      results.append(result)
      builder.AND(fake_verifier)

    # verify build can work multiple times
    self.assertEqual(builder.build(), builder.build())
    verifier = builder.build()
    self.assertEqual([verifiers], verifier.dnf_verifiers)

    expect = _makeObservationVerifyResult(
        False, bad_results=[pred_results[0]])

    global _called_verifiers
    _called_verifiers = []
    got = verifier(context, jc.Observation())

    self.assertEqual(expect, got)
    self.assertEqual(verifiers[:1], _called_verifiers)
  def test_result_observation_verifier_conjunction_ok(self):
    context = ExecutionContext()
    builder = jc.ObservationVerifierBuilder(title='Test')
    verifiers = []
    pred_results = []
    for i in range(3):
      this_result = jp.PredicateResult(True, comment='Pred {0}'.format(i))
      pred_results.append(this_result)
      result = _makeObservationVerifyResult(
          valid=True, good_results=[this_result])
      fake_verifier = FakeObservationVerifier(
          title=i, dnf_verifier=[], result=result)
      verifiers.append(fake_verifier)
      builder.AND(fake_verifier)

    # verify build can work multiple times
    self.assertEqual(builder.build(), builder.build())
    verifier = builder.build()
    self.assertEqual([verifiers], verifier.dnf_verifiers)

    expect = _makeObservationVerifyResult(True, good_results=pred_results)

    global _called_verifiers
    _called_verifiers = []
    got = verifier(context, jc.Observation())

    self.assertEqual(expect, got)
    self.assertEqual(verifiers, _called_verifiers)
Example #16
0
  def test_collect_with_dict_subset(self):
    # See test_dict_subset_with_array_nodes for comparision.
    context = ExecutionContext()
    letters = {'a':'A', 'b':'B', 'c':'C'}
    numbers = {'a':1, 'b':2}
    both = [letters, numbers]
    source = {'items': both}
    letter_subset_pred = jp.DICT_SUBSET({'a':'A'})
    path_pred = jp.PathPredicate('items', pred=letter_subset_pred)
    result = path_pred(context, source)

    mismatch_error = jp.TypeMismatchError(
        expect_type=(int, long, float), got_type=str,
        source=source,
        target_path=jp.PATH_SEP.join(['items', 'a']),
        path_value=PathValue('items[1]', numbers))
    valid_result = letter_subset_pred(context, letters).clone_with_source(
        source=source, base_target_path='items', base_value_path='items[0]')
    self.assertEqual(
        # pylint: disable=bad-continuation
        jp.PathPredicateResultBuilder(source, path_pred)
          .add_result_candidate(PathValue('items[0]', letters), valid_result)
          .add_result_candidate(PathValue('items[1]', numbers),
                                mismatch_error)
          .build(True),
        result)
Example #17
0
 def test_string_ne(self):
   context = ExecutionContext()
   ne_abc = jp.STR_NE('abc')
   self.assertGoodResult(PathValue('', 'abcd'),
                         ne_abc, ne_abc(context, 'abcd'))
   self.assertBadResult(PathValue('', 'abc'),
                        ne_abc, ne_abc(context, 'abc'))
Example #18
0
 def test_empty_builder(self):
   context = ExecutionContext()
   agent = self.testing_agent
   contract_builder = gt.GcpContractBuilder(agent)
   contract = contract_builder.build()
   results = contract.verify(context)
   self.assertTrue(results)
Example #19
0
    def test_collect_from_nested_list_found(self):
        # """Ambiguous path through nested lists."""
        context = ExecutionContext()
        source = {'outer': [_LETTER_DICT, _NUMBER_DICT]}
        pred = PathPredicate(PATH_SEP.join(['outer', 'a']))
        values = pred(context, source)
        self.assertEqual([
            PathValue(PATH_SEP.join(['outer[0]', 'a']), 'A'),
            PathValue(PATH_SEP.join(['outer[1]', 'a']), 1)
        ], values.path_values)

        pred = PathPredicate(PATH_SEP.join(['outer', 'z']))
        values = pred(context, source)
        self.assertEqual([PathValue(PATH_SEP.join(['outer[0]', 'z']), 'Z')],
                         values.path_values)
        self.assertEqual([
            MissingPathError(_NUMBER_DICT,
                             'z',
                             path_value=PathValue('outer[1]', _NUMBER_DICT))
        ], values.path_failures)

        pred = PathPredicate(PATH_SEP.join(['outer', 'three']))
        values = pred(context, source)
        self.assertEqual([PathValue(PATH_SEP.join(['outer[1]', 'three']), 3)],
                         values.path_values)
        self.assertEqual([
            MissingPathError(_LETTER_DICT,
                             'three',
                             path_value=PathValue('outer[0]', _LETTER_DICT))
        ], values.path_failures)
Example #20
0
  def test_inspect_not_found_ok(self):
    context = ExecutionContext()
    response = Mock()
    response.status = 404
    response.reason = 'Not Found'
    default_variables = {'project': 'PROJECT'}
    service = MyFakeGcpService([HttpError(response, 'Not Found')])
    agent = TestGcpAgent.make_test_agent(
        service=service, default_variables=default_variables)


    contract_builder = gt.GcpContractBuilder(agent)

    c1 = contract_builder.new_clause_builder('TITLE')
    verifier = c1.inspect_resource(
        'regions', resource_id='us-central1-f', no_resource_ok=True)
    verifier.contains_path_value('field', 'value')
    self.assertTrue(isinstance(verifier, jc.ValueObservationVerifierBuilder))

    contract = contract_builder.build()
    verification_result = contract.verify(context)
    self.assertTrue(verification_result,
                    JsonSnapshotHelper.ValueToEncodedJson(verification_result))
    self.assertEquals({'project': 'PROJECT', 'region': 'us-central1-f'},
                      agent.service.last_get_args)
 def test_string_specific_operator_type_mismatch(self):
     context = ExecutionContext()
     operand = 'valid string operand.'
     for value in [['value'], {'a': 'A'}, 1]:
         for factory in [jp.STR_SUBSTR]:
             self.simple_operand_type_mismatch_helper(
                 context, basestring, factory, operand, value)
    def test_bad(self):
        context = ExecutionContext()
        source = [{
            'metric': 'A',
            'limit': 100.0,
            'usage': 0.0
        }, {
            'metric': 'B',
            'limit': 100.0,
            'usage': 90.0
        }, {
            'metric': 'C',
            'limit': 100.0,
            'usage': 100.0
        }]
        require = {'A': 95.0, 'B': 15.0}
        pred = QuotaPredicate(require)
        builder = KeyedPredicateResultBuilder(pred)
        builder.add_result(
            'A', make_quota_result(context, True, source, require, 'A'))
        builder.add_result(
            'B', make_quota_result(context, False, source, require, 'B'))
        builder.comment = 'Insufficient C.'

        result = pred(context, source)
        self.assertFalse(result)
Example #23
0
    def __elem_exists(self, agent, resource_type, elem, aggregated):
        """Determine if a pending delete on an instance has completed or not."""
        context = ExecutionContext()
        params = {}
        if aggregated:
            name = elem[1]
            param_name, param_value = elem[0].split('/', 1)
            if param_name[-1] == 's':
                param_name = param_name[:-1]

            # Just because the aggregation returned a parameter
            # does not mean the get API takes it. Confirm before adding.
            if (agent.resource_type_to_discovery_info(resource_type).get(
                    'methods', {}).get('get', {}).get('parameters',
                                                      {}).get(param_name)):
                params[param_name] = param_value

        name = elem[1] if aggregated else elem
        try:
            agent.get_resource(context,
                               resource_type,
                               resource_id=name,
                               **params)
            return True
        except HttpError as http_error:
            if http_error.resp.status == HTTPStatus.NOT_FOUND:
                return False
            if http_error.resp.status in self.__RETRYABLE_DELETE_HTTP_CODES:
                return True
            print('Unexpected error while waiting for delete: {0} {1}={2}'.
                  format(resource_type, name, http_error))

        return False
    def test_contract_bad(self):
        context = ExecutionContext()
        source = [{
            'metric': 'A',
            'limit': 100.0,
            'usage': 0.0
        }, {
            'metric': 'B',
            'limit': 100.0,
            'usage': 90.0
        }, {
            'metric': 'C',
            'limit': 100.0,
            'usage': 100.0
        }]
        mock_service = self.make_mock_service(source, source)
        observer = GcpAgent(service=mock_service,
                            discovery_doc=MOCK_DISCOVERY,
                            default_variables={'project': 'PROJECT'})

        project_quota = {'A': 95.0, 'B': 10.0}
        regions = [('region1', project_quota), ('region2', {'C': 1.0})]

        contract = make_quota_contract(observer, project_quota, regions)
        result = contract.verify(context)
        self.assertFalse(result)
        self.assertEqual(3, len(result.clause_results))
        self.assertTrue(result.clause_results[0])
        self.assertTrue(result.clause_results[1])
        self.assertFalse(result.clause_results[2])
Example #25
0
    def mixed_exclude_helper(self, strict):
        context = ExecutionContext()
        observation = jc.Observation()
        observation.add_object('A')
        observation.add_object('B')
        observation.add_object('C')
        fake_observer = FakeObserver(observation)

        # We dont expect to see B in the list.
        # This can be interpreted two ways -- strictly or not strictly.
        # Strictly means no results should ever contain B.
        # Non strict means some result should not contain B.
        builder = jc.ValueObservationVerifierBuilder('Test Excludes',
                                                     strict=strict)
        builder.excludes_path_value(None, 'B')

        clause = jc.ContractClause('TestClause', fake_observer,
                                   builder.build())
        contract = jc.Contract()
        contract.add_clause(clause)

        # Doesnt matter whether strict or not since this is checking cardinality
        # over the entire list via the excludes clause.
        expect_result = jc.contract.ContractVerifyResult(
            False, [clause.verify(context)])
        result = contract.verify(context)
        self.assertEqual(expect_result, result)
        self.assertEqual(False, result.valid)
    def test_good(self):
        context = ExecutionContext()
        source = [{
            'metric': 'A',
            'limit': 100.0,
            'usage': 0.0
        }, {
            'metric': 'B',
            'limit': 100.0,
            'usage': 90.0
        }, {
            'metric': 'C',
            'limit': 100.0,
            'usage': 100.0
        }]
        require = {'A': 95.0, 'B': 10.0}
        pred = QuotaPredicate(require)
        builder = KeyedPredicateResultBuilder(pred)
        builder.add_result(
            'A', make_quota_result(context, True, source, require, 'A'))
        builder.add_result(
            'B', make_quota_result(context, True, source, require, 'B'))
        builder.comment = 'Satisfied all 2 metrics.'

        result = pred(context, source)
        self.assertTrue(result)
        self.assertEqual(result, builder.build(True))
Example #27
0
  def test_condition_else_success(self):
    context = ExecutionContext(a='A', b='B', c='C')
    aA = jp.PathEqPredicate('a', lambda x: x['a'])
    bB = jp.PathEqPredicate('b', lambda x: x['b'])
    cC = jp.PathEqPredicate('c', lambda x: x['c'])

    ifAthenBelseC = jc.IF(aA, bB, cC)

    # True if all conditions are true.
    # True if "if" satisfied and "then" matches.
    # True if only else condition is true.
    test_cases = [_LETTER_DICT,
                  {'a':'A', 'b':'B', 'c':'X'},
                  {'a':'X', 'b':'B', 'c':'C'},
                  {'a':'X', 'b':'X', 'c':'C'},
                 ]

    for i in range(3):
      test = test_cases[i]
      tried = [aA(context, test)]
      if i < 2:
        # First two have true IF to just execute THEN
        tried.append(bB(context, test))
      else:
        # Remainder have false IF to just execute ELSE
        tried.append(cC(context, test))

      expect = jc.CompositePredicateResult(
          valid=True, pred=ifAthenBelseC, results=tried)
      result = ifAthenBelseC(context, test)
      self.assertTrue(result)
      self.assertEqual(expect, result)
Example #28
0
 def test_standard_string_operator_type_mismatch(self):
   context = ExecutionContext()
   for value in [['value'], {'a':'A'}, 1]:
     for factory in [jp.STR_EQ, jp.STR_NE]:
       self.standard_operand_type_mismatch_helper(
           context, basestring, factory,
           good_operand='test value', bad_operand=value)
Example #29
0
    def test_list(self):
        # Return a list of two objects -- a dictionary and an array.
        context = ExecutionContext()
        default_response = st.CliResponseType(0,
                                              '[{"field":"value"}, [1,2,3]]',
                                              '')

        gcloud = fake_gcloud_agent.FakeGCloudAgent(
            'PROJECT', 'ZONE', default_response=default_response)
        contract_builder = gt.GCloudContractBuilder(gcloud)

        c1 = contract_builder.new_clause_builder('TITLE')
        extra_args = ['arg1', 'arg2', 'arg3']
        verifier = c1.list_resources('instances', extra_args=extra_args)
        verifier.contains_path_value('field', 'value')

        self.assertTrue(
            isinstance(verifier, jc.ValueObservationVerifierBuilder))

        # When we build and run the contract, it is going to call the observer.
        # The clause has no constraints so it will succeed. We do this so that
        # we can verify the contract will call the clause which in turn will
        # call the agent with the expected parameters we test for below.
        contract = contract_builder.build()
        self.assertTrue(contract.verify(context))

        command = gcloud.build_gcloud_command_args('instances',
                                                   ['list'] + extra_args,
                                                   project='PROJECT')
        self.assertEquals(command, gcloud.last_run_params)
Example #30
0
 def test_standard_dict_operator_type_mismatch(self):
   context = ExecutionContext()
   operand = {'a': 'A'}
   for value in [['a'], 'a', 1]:
     for factory in [jp.DICT_EQ, jp.DICT_NE]:
       self.standard_operand_type_mismatch_helper(
           context, dict, factory, good_operand=operand, bad_operand=value)