Example #1
0
    def delete_app(self):
        contract = jc.Contract()

        app_url_path = "/".join(["/v2/applications", self.TEST_APP])
        f50_builder = st.http_observer.HttpContractBuilder(self.agent)
        # The application should be unlisted immediately (assuming 1 replica)
        # However given GCS rate limiting on updating the timestamp file,
        # there is a race condition in which the filesystem timestamp
        # was rate limited from updating AND a scheduled update is in progress
        # where the application was seen just before the delete so gets restored
        # back. Because the timestamp was not updated, this observer will read
        # from the cache thinking it is fresh. We need the extra second to allow
        # for the retry on the timestamp update to write out to GCS.
        (f50_builder.new_clause_builder(
            "Unlists Application",
            retryable_for_secs=8).get_url_path("/v2/applications").EXPECT(
                ov_factory.value_list_path_excludes(
                    "name", jp.STR_SUBSTR(self.TEST_APP.upper()))))
        (f50_builder.new_clause_builder("Deletes Application").get_url_path(
            app_url_path).EXPECT(
                ov_factory.error_list_contains(
                    st.HttpAgentErrorPredicate(
                        st.HttpResponsePredicate(http_code=404)))))

        (f50_builder.new_clause_builder(
            "History Retains Application", retryable_for_secs=5).get_url_path(
                "/v2/applications/{app}/history".format(
                    app=self.TEST_APP)).EXPECT(
                        ov_factory.value_list_matches([
                            jp.DICT_MATCHES({
                                key: jp.EQUIVALENT(value)
                                for key, value in self.app_history[0].items()
                            }),
                            jp.DICT_MATCHES({
                                key: jp.EQUIVALENT(value)
                                for key, value in self.app_history[1].items()
                            }),
                        ])))

        for clause in f50_builder.build().clauses:
            contract.add_clause(clause)

        gcs_builder = gcp.GcpStorageContractBuilder(self.gcs_observer)
        (gcs_builder.new_clause_builder(
            "Deleted File", retryable_for_secs=5).list_bucket(
                self.BUCKET, "/".join([self.BASE_PATH,
                                       "applications"])).EXPECT(
                                           ov_factory.value_list_path_excludes(
                                               "name",
                                               jp.STR_SUBSTR(self.TEST_APP))))
        for clause in gcs_builder.build().clauses:
            contract.add_clause(clause)

        return st.OperationContract(
            self.new_delete_operation(title="delete_app",
                                      data=None,
                                      path=app_url_path),
            contract=contract,
        )
Example #2
0
  def test_k_expect_observe_error(self):
    """Example expects the observation itself to fail."""
    key = self.make_key('InvalidKey')
    context = citest.base.ExecutionContext()

    builder = st.HttpContractBuilder(self.scenario.agent)
    (builder.new_clause_builder('Expect Not Found Error')
     .get_url_path('/lookup/' + key)
     .EXPECT(ov_factory.error_list_contains(
         st.HttpAgentErrorPredicate(st.HttpResponsePredicate(http_code=404)))))
    contract = builder.build()
    results = contract.verify(context)
    self.assertTrue(results)
Example #3
0
    def delete_app(self):
        contract = jc.Contract()

        app_url_path = '/'.join(['/v2/applications', self.TEST_APP])
        f50_builder = st.http_observer.HttpContractBuilder(self.agent)
        (f50_builder.new_clause_builder('Unlists Application').get_url_path(
            '/v2/applications').EXPECT(
                ov_factory.value_list_path_excludes(
                    'name', jp.STR_SUBSTR(self.TEST_APP.upper()))))
        (f50_builder.new_clause_builder('Deletes Application').get_url_path(
            app_url_path).EXPECT(
                ov_factory.error_list_contains(
                    st.HttpAgentErrorPredicate(
                        st.HttpResponsePredicate(http_code=404)))))

        (f50_builder.new_clause_builder(
            'History Retains Application', retryable_for_secs=5).get_url_path(
                '/v2/applications/{app}/history'.format(
                    app=self.TEST_APP)).EXPECT(
                        ov_factory.value_list_matches([
                            jp.DICT_MATCHES({
                                key: jp.EQUIVALENT(value)
                                for key, value in self.app_history[0].items()
                            }),
                            jp.DICT_MATCHES({
                                key: jp.EQUIVALENT(value)
                                for key, value in self.app_history[1].items()
                            })
                        ])))

        for clause in f50_builder.build().clauses:
            contract.add_clause(clause)

        gcs_builder = gcp.GcpStorageContractBuilder(self.gcs_observer)
        (gcs_builder.new_clause_builder(
            'Deleted File', retryable_for_secs=5).list_bucket(
                self.BUCKET, '/'.join([self.BASE_PATH,
                                       'applications'])).EXPECT(
                                           ov_factory.value_list_path_excludes(
                                               'name',
                                               jp.STR_SUBSTR(self.TEST_APP))))
        for clause in gcs_builder.build().clauses:
            contract.add_clause(clause)

        return st.OperationContract(self.new_delete_operation(
            title='delete_app', data=None, path=app_url_path),
                                    contract=contract)