def check_server_groups_endpoint(self, kind, image, has_lb=True): name = self.TEST_APP + '-' + kind account = self.bindings['SPINNAKER_KUBERNETES_V2_ACCOUNT'] builder = HttpContractBuilder(self.agent) lb_pred = ( jp.LIST_MATCHES([jp.STR_EQ('service {}-service'.format(self.TEST_APP))]) if has_lb else jp.LIST_EQ([]) ) (builder.new_clause_builder('Has recorded a server group for the deployed manifest') .get_url_path('/applications/{}/serverGroups'.format(self.TEST_APP)) .EXPECT( ov_factory.value_list_contains(jp.DICT_MATCHES({ 'name': jp.STR_SUBSTR(name), 'cluster': jp.STR_EQ(kind + ' ' + name), 'account': jp.STR_EQ(account), 'cloudProvider': jp.STR_EQ('kubernetes'), 'buildInfo': jp.DICT_MATCHES({ 'images': jp.LIST_MATCHES([jp.STR_EQ(image)]), }), 'loadBalancers': lb_pred, })) )) return st.OperationContract( NoOpOperation('Has recorded a server group'), contract=builder.build())
def check_load_balancers_endpoint(self, kind): name = kind + ' ' + self.TEST_APP + '-' + kind account = self.bindings['SPINNAKER_KUBERNETES_V2_ACCOUNT'] builder = HttpContractBuilder(self.agent) (builder.new_clause_builder( 'Has recorded a load balancer', retryable_for_secs=120).get_url_path( '/applications/{}/loadBalancers'.format(self.TEST_APP)).EXPECT( ov_factory.value_list_contains( jp.DICT_MATCHES({ 'name': jp.STR_EQ(name), 'kind': jp.STR_EQ(kind), 'account': jp.STR_EQ(account), 'cloudProvider': jp.STR_EQ('kubernetes'), 'serverGroups': jp.LIST_MATCHES([ jp.DICT_MATCHES({ 'account': jp.STR_EQ(account), 'name': jp.STR_SUBSTR(self.TEST_APP), }), ]), })))) return st.OperationContract( NoOpOperation('Has recorded a load balancer'), contract=builder.build())
def check_server_groups_endpoint(self, kind, image, has_lb=True): name = self.TEST_APP + '-' + kind account = self.bindings['SPINNAKER_KUBERNETES_V2_ACCOUNT'] builder = HttpContractBuilder(self.agent) lb_pred = (jp.LIST_MATCHES([ jp.STR_EQ('service {}-service'.format(self.TEST_APP)) ]) if has_lb else jp.LIST_EQ([])) (builder.new_clause_builder( 'Has recorded a server group for the deployed manifest', retryable_for_secs=120).get_url_path( '/applications/{}/serverGroups'.format(self.TEST_APP)).EXPECT( ov_factory.value_list_contains( jp.DICT_MATCHES({ 'name': jp.STR_SUBSTR(name), 'cluster': jp.STR_EQ(kind + ' ' + name), 'account': jp.STR_EQ(account), 'cloudProvider': jp.STR_EQ('kubernetes'), 'buildInfo': jp.DICT_MATCHES({ 'images': jp.LIST_MATCHES([jp.STR_EQ(image)]), }), 'loadBalancers': lb_pred, })))) return st.OperationContract( NoOpOperation('Has recorded a server group'), contract=builder.build())
def check_detailed_clusters_endpoint(self, kind): name = kind + ' ' + self.TEST_APP + '-' + kind url_name = name.replace(' ', '%20') account = self.bindings['SPINNAKER_KUBERNETES_V2_ACCOUNT'] builder = HttpContractBuilder(self.agent) (builder.new_clause_builder( 'Has recorded a cluster for the deployed manifest').get_url_path( '/applications/{app}/clusters/{account}/{name}'.format( app=self.TEST_APP, account=account, name=url_name)).EXPECT( ov_factory.value_list_contains( jp.DICT_MATCHES({ 'accountName': jp.STR_EQ(account), 'name': jp.STR_EQ(name), 'serverGroups': jp.LIST_MATCHES([ jp.DICT_MATCHES({ 'account': jp.STR_EQ(account), }) ]), })))) return st.OperationContract(NoOpOperation('Has recorded a cluster'), contract=builder.build())
def check_load_balancers_endpoint_empty(self): builder = HttpContractBuilder(self.agent) (builder.new_clause_builder('Has no load balancer').get_url_path( '/applications/{}/loadBalancers'.format(self.TEST_APP)).EXPECT( ov_factory.value_list_matches([]))) return st.OperationContract(NoOpOperation('Has no load balancer'), contract=builder.build())
def list_available_images(self): """Creates a test that confirms expected available images. Returns: st.OperationContract """ logger = logging.getLogger(__name__) # Get the list of images available (to the service account we are using). context = citest.base.ExecutionContext() gcp_agent = self.gcp_observer JournalLogger.begin_context("Collecting expected available images") relation_context = "ERROR" try: logger.debug("Looking up available images.") json_doc = gcp_agent.list_resource(context, "images") for project in GCP_STANDARD_IMAGES.keys(): logger.info("Looking for images from project=%s", project) found = gcp_agent.list_resource(context, "images", project=project) for image in found: if not image.get("deprecated", None): json_doc.append(image) # Produce the list of images that we expect to receive from spinnaker # (visible to the primary service account). spinnaker_account = self.bindings["SPINNAKER_GOOGLE_ACCOUNT"] logger.debug('Configured with Spinnaker account "%s"', spinnaker_account) expect_images = [{ "account": spinnaker_account, "imageName": image["name"] } for image in json_doc] expect_images = sorted(expect_images, key=lambda k: k["imageName"]) relation_context = "VALID" finally: JournalLogger.end_context(relation=relation_context) # pylint: disable=bad-continuation builder = HttpContractBuilder(self.agent) (builder.new_clause_builder("Has Expected Images").get_url_path( "/gce/images/find").EXPECT( ov_factory.value_list_matches( [ jp.DICT_SUBSET(image_entry) for image_entry in expect_images ], strict=True, unique=True, ))) return st.OperationContract(NoOpOperation("List Available Images"), contract=builder.build())
def list_available_images(self): """Creates a test that confirms expected available images. Returns: st.OperationContract """ logger = logging.getLogger(__name__) # Get the list of images available (to the service account we are using). context = citest.base.ExecutionContext() gcp_agent = self.gcp_observer JournalLogger.begin_context('Collecting expected available images') relation_context = 'ERROR' try: logger.debug('Looking up available images.') json_doc = gcp_agent.list_resource(context, 'images') for project in GCP_STANDARD_IMAGES.keys(): logger.info('Looking for images from project=%s', project) found = gcp_agent.list_resource(context, 'images', project=project) for image in found: if not image.get('deprecated', None): json_doc.append(image) # Produce the list of images that we expect to receive from spinnaker # (visible to the primary service account). spinnaker_account = self.agent.deployed_config.get( 'providers.google.primaryCredentials.name') logger.debug('Configured with Spinnaker account "%s"', spinnaker_account) expect_images = [{ 'account': spinnaker_account, 'imageName': image['name'] } for image in json_doc] expect_images = sorted(expect_images, key=lambda k: k['imageName']) relation_context = 'VALID' finally: JournalLogger.end_context(relation=relation_context) # pylint: disable=bad-continuation builder = HttpContractBuilder(self.agent) (builder.new_clause_builder('Has Expected Images').get_url_path( '/gce/images/find').contains_match( [jp.DICT_SUBSET(image_entry) for image_entry in expect_images], match_kwargs={ 'strict': True, 'unique': True })) return st.OperationContract(NoOpOperation('List Available Images'), contract=builder.build())
def test_contract_ok(self): builder = HttpContractBuilder(self.agent) # Here we're setting the observer_factory to make an HttpResponseObserver # so that the observation objects are the HttpResponseType instance rather # than the normal HttpObjectObserver where the objects are the payload data. (builder.new_clause_builder('Expect OK') .get_url_path('testpath?code=202', observer_factory=HttpResponseObserver) .EXPECT(ov_factory.value_list_contains(HttpResponsePredicate(http_code=202)))) contract = builder.build() results = contract.verify(self.context) self.assertTrue(results)
def test_contract_ok(self): builder = HttpContractBuilder(self.agent) # Here we're setting the observer_factory to make an HttpResponseObserver # so that the observation objects are the HttpResponseType instance rather # than the normal HttpObjectObserver where the objects are the payload data. (builder.new_clause_builder('Expect OK').get_url_path( 'testpath?code=202', observer_factory=HttpResponseObserver).EXPECT( ov_factory.value_list_contains( HttpResponsePredicate(http_code=202)))) contract = builder.build() results = contract.verify(self.context) self.assertTrue(results)
def check_manifest_endpoint_exists(self, kind): name = self.TEST_APP + '-' + kind account = self.bindings['SPINNAKER_KUBERNETES_V2_ACCOUNT'] builder = HttpContractBuilder(self.agent) (builder.new_clause_builder('Has recorded a manifest').get_url_path( '/manifests/{account}/{namespace}/{name}'.format( account=account, namespace=self.TEST_NAMESPACE, name='{}%20{}'.format(kind, name))).EXPECT( ov_factory.value_list_contains( jp.DICT_MATCHES({'account': jp.STR_EQ(account)})))) return st.OperationContract(NoOpOperation('Has recorded a manifest'), contract=builder.build())
def list_available_images(self): """Creates a test that confirms expected available images. Returns: st.OperationContract """ logger = logging.getLogger(__name__) # Get the list of images available (to the service account we are using). context = citest.base.ExecutionContext() gcp_agent = self.gcp_observer JournalLogger.begin_context('Collecting expected available images') relation_context = 'ERROR' try: logger.debug('Looking up available images.') json_doc = gcp_agent.list_resource(context, 'images') for project in GCP_STANDARD_IMAGES.keys(): logger.info('Looking for images from project=%s', project) found = gcp_agent.list_resource(context, 'images', project=project) for image in found: if not image.get('deprecated', None): json_doc.append(image) # Produce the list of images that we expect to receive from spinnaker # (visible to the primary service account). spinnaker_account = self.bindings['SPINNAKER_GOOGLE_ACCOUNT'] logger.debug('Configured with Spinnaker account "%s"', spinnaker_account) expect_images = [{'account': spinnaker_account, 'imageName': image['name']} for image in json_doc] expect_images = sorted(expect_images, key=lambda k: k['imageName']) relation_context = 'VALID' finally: JournalLogger.end_context(relation=relation_context) # pylint: disable=bad-continuation builder = HttpContractBuilder(self.agent) (builder.new_clause_builder('Has Expected Images') .get_url_path('/gce/images/find') .EXPECT( ov_factory.value_list_matches( [jp.DICT_SUBSET(image_entry) for image_entry in expect_images], strict=True, unique=True))) return st.OperationContract( NoOpOperation('List Available Images'), contract=builder.build())
def check_applications_endpoint(self): account = self.bindings['SPINNAKER_KUBERNETES_V2_ACCOUNT'] builder = HttpContractBuilder(self.agent) (builder.new_clause_builder('Has recorded an app for the deployed manifest') .get_url_path('/applications') .EXPECT( ov_factory.value_list_contains(jp.DICT_MATCHES({ 'name': jp.STR_EQ(self.TEST_APP), 'accounts': jp.STR_SUBSTR(account), })) )) return st.OperationContract( NoOpOperation('Has recorded an application'), contract=builder.build())
def check_applications_endpoint(self): account = self.bindings['SPINNAKER_KUBERNETES_V2_ACCOUNT'] builder = HttpContractBuilder(self.agent) (builder.new_clause_builder( 'Has recorded an app for the deployed manifest', retryable_for_secs=120).get_url_path('/applications').EXPECT( ov_factory.value_list_contains( jp.DICT_MATCHES({ 'name': jp.STR_EQ(self.TEST_APP), 'accounts': jp.STR_SUBSTR(account), })))) return st.OperationContract( NoOpOperation('Has recorded an application'), contract=builder.build())
def check_clusters_endpoint(self, kind): name = kind + ' ' + self.TEST_APP + '-' + kind account = self.bindings['SPINNAKER_KUBERNETES_V2_ACCOUNT'] builder = HttpContractBuilder(self.agent) (builder.new_clause_builder('Has recorded a cluster for the deployed manifest') .get_url_path('/applications/{}/clusters'.format(self.TEST_APP)) .EXPECT( ov_factory.value_list_contains(jp.DICT_MATCHES({ account: jp.LIST_MATCHES([jp.STR_EQ(name)]), })) )) return st.OperationContract( NoOpOperation('Has recorded a cluster'), contract=builder.build())
def check_clusters_endpoint(self, kind): name = kind + ' ' + self.TEST_APP + '-' + kind account = self.bindings['SPINNAKER_KUBERNETES_V2_ACCOUNT'] builder = HttpContractBuilder(self.agent) (builder.new_clause_builder( 'Has recorded a cluster for the deployed manifest').get_url_path( '/applications/{}/clusters'.format(self.TEST_APP)).EXPECT( ov_factory.value_list_contains( jp.DICT_MATCHES({ account: jp.LIST_MATCHES([jp.STR_EQ(name)]), })))) return st.OperationContract(NoOpOperation('Has recorded a cluster'), contract=builder.build())
def list_available_images(self): """Creates a test that confirms expected available images. Returns: st.OperationContract """ logger = logging.getLogger(__name__) # Get the list of images available (to the service account we are using). context = citest.base.ExecutionContext() gcp_agent = self.gcp_observer JournalLogger.begin_context('Collecting expected available images') relation_context = 'ERROR' try: logger.debug('Looking up available images.') json_doc = gcp_agent.list_resource(context, 'images') for project in GCP_STANDARD_IMAGES.keys(): logger.info('Looking for images from project=%s', project) found = gcp_agent.list_resource(context, 'images', project=project) for image in found: if not image.get('deprecated', None): json_doc.append(image) # Produce the list of images that we expect to receive from spinnaker # (visible to the primary service account). spinnaker_account = self.agent.deployed_config.get( 'providers.google.primaryCredentials.name') logger.debug('Configured with Spinnaker account "%s"', spinnaker_account) expect_images = [{'account': spinnaker_account, 'imageName': image['name']} for image in json_doc] expect_images = sorted(expect_images, key=lambda k: k['imageName']) relation_context = 'VALID' finally: JournalLogger.end_context(relation=relation_context) # pylint: disable=bad-continuation builder = HttpContractBuilder(self.agent) (builder.new_clause_builder('Has Expected Images') .get_url_path('/gce/images/find') .add_constraint(jp.PathPredicate(jp.DONT_ENUMERATE_TERMINAL, jp.EQUIVALENT(expect_images)))) return st.OperationContract( NoOpOperation('List Available Images'), contract=builder.build())
def check_manifest_endpoint_exists(self, kind): name = self.TEST_APP + '-' + kind account = self.bindings['SPINNAKER_KUBERNETES_V2_ACCOUNT'] builder = HttpContractBuilder(self.agent) (builder.new_clause_builder('Has recorded a manifest') .get_url_path('/manifests/{account}/{namespace}/{name}'.format( account=account, namespace=self.TEST_NAMESPACE, name='{}%20{}'.format(kind, name) )) .EXPECT( ov_factory.value_list_contains(jp.DICT_MATCHES({ 'account': jp.STR_EQ(account) })) )) return st.OperationContract( NoOpOperation('Has recorded a manifest'), contract=builder.build())
def list_available_images(self): """Creates a test that confirms expected available images. Returns: st.OperationContract """ logger = logging.getLogger(__name__) # Get the list of images available (to the service account we are using). gcloud_agent = self.gce_observer service_account = self.bindings.get('GCE_SERVICE_ACCOUNT', None) extra_args = ['--account', service_account] if service_account else [] logger.debug('Looking up available images.') cli_result = gcloud_agent.list_resources('images', extra_args=extra_args) if not cli_result.ok(): raise RuntimeError('GCloud failed with: {0}'.format( str(cli_result))) json_doc = json_module.JSONDecoder().decode(cli_result.output) # Produce the list of images that we expect to receive from spinnaker # (visible to the primary service account). spinnaker_account = self.agent.deployed_config.get( 'providers.google.primaryCredentials.name') logger.debug('Configured with Spinnaker account "%s"', spinnaker_account) expect_images = [{ 'account': spinnaker_account, 'imageName': image['name'] } for image in json_doc] expect_images = sorted(expect_images, key=lambda k: k['imageName']) # pylint: disable=bad-continuation builder = HttpContractBuilder(self.agent) (builder.new_clause_builder('Has Expected Images').get_url_path( '/gce/images/find').add_constraint( jp.PathPredicate(jp.DONT_ENUMERATE_TERMINAL, jp.EQUIVALENT(expect_images)))) return st.OperationContract(NoOpOperation('List Available Images'), contract=builder.build())
def test_contract_failure_ok(self): builder = HttpContractBuilder(self.agent) # Here we're setting the observer_factory to make an HttpResponseObserver # so that the observation objects are the HttpResponseType instance rather # than the normal HttpObjectObserver where the objects are the payload data. # # When we encounter the HTTP error, the HttpResponseType is wrapped in an # HttpAgentError object and put into the observation error list. # So we need to dig it back out of there. # In addition, we're using error_list_matches rather than error_list_contains # so we can strict=True to show exactly the one error. "matches" takes a list # of predicates, so we wrap the error check into a list. (builder.new_clause_builder('Expect NotFound') .get_url_path('testpath?code=404', observer_factory=HttpResponseObserver) .EXPECT(ov_factory.error_list_matches( [HttpAgentErrorPredicate(HttpResponsePredicate(http_code=404))], strict=True))) # Only the one error in the list contract = builder.build() results = contract.verify(self.context) self.assertTrue(results)
def list_available_images(self): """Creates a test that confirms expected available images. Returns: st.OperationContract """ logger = logging.getLogger(__name__) # Get the list of images available (to the service account we are using). gcloud_agent = self.gce_observer service_account = self.bindings.get('GCE_SERVICE_ACCOUNT', None) extra_args = ['--account', service_account] if service_account else [] logger.debug('Looking up available images.') cli_result = gcloud_agent.list_resources('images', extra_args=extra_args) if not cli_result.ok(): raise RuntimeError('GCloud failed with: {0}'.format(str(cli_result))) json_doc = json_module.JSONDecoder().decode(cli_result.output) # Produce the list of images that we expect to receive from spinnaker # (visible to the primary service account). spinnaker_account = self.agent.deployed_config.get( 'providers.google.primaryCredentials.name') logger.debug('Configured with Spinnaker account "%s"', spinnaker_account) expect_images = [{'account': spinnaker_account, 'imageName': image['name']} for image in json_doc] expect_images = sorted(expect_images, key=lambda k: k['imageName']) # pylint: disable=bad-continuation builder = HttpContractBuilder(self.agent) (builder.new_clause_builder('Has Expected Images') .get_url_path('/gce/images/find') .add_constraint(jp.PathPredicate(jp.DONT_ENUMERATE_TERMINAL, jp.EQUIVALENT(expect_images)))) return st.OperationContract( NoOpOperation('List Available Images'), contract=builder.build())
def check_detailed_clusters_endpoint(self, kind): name = kind + ' ' + self.TEST_APP + '-' + kind url_name = name.replace(' ', '%20') account = self.bindings['SPINNAKER_KUBERNETES_V2_ACCOUNT'] builder = HttpContractBuilder(self.agent) (builder.new_clause_builder('Has recorded a cluster for the deployed manifest') .get_url_path('/applications/{app}/clusters/{account}/{name}'.format( app=self.TEST_APP, account=account, name=url_name)) .EXPECT( ov_factory.value_list_contains(jp.DICT_MATCHES({ 'accountName': jp.STR_EQ(account), 'name': jp.STR_EQ(name), 'serverGroups': jp.LIST_MATCHES([ jp.DICT_MATCHES({ 'account': jp.STR_EQ(account), }) ]), })) )) return st.OperationContract( NoOpOperation('Has recorded a cluster'), contract=builder.build())
def test_contract_failure_ok(self): builder = HttpContractBuilder(self.agent) # Here we're setting the observer_factory to make an HttpResponseObserver # so that the observation objects are the HttpResponseType instance rather # than the normal HttpObjectObserver where the objects are the payload data. # # When we encounter the HTTP error, the HttpResponseType is wrapped in an # HttpAgentError object and put into the observation error list. # So we need to dig it back out of there. # In addition, we're using error_list_matches rather than error_list_contains # so we can strict=True to show exactly the one error. "matches" takes a list # of predicates, so we wrap the error check into a list. (builder.new_clause_builder('Expect NotFound').get_url_path( 'testpath?code=404', observer_factory=HttpResponseObserver).EXPECT( ov_factory.error_list_matches([ HttpAgentErrorPredicate( HttpResponsePredicate(http_code=404)) ], strict=True)) ) # Only the one error in the list contract = builder.build() results = contract.verify(self.context) self.assertTrue(results)
def check_load_balancers_endpoint(self, kind): name = kind + ' ' + self.TEST_APP + '-' + kind account = self.bindings['SPINNAKER_KUBERNETES_V2_ACCOUNT'] builder = HttpContractBuilder(self.agent) (builder.new_clause_builder('Has recorded a load balancer') .get_url_path('/applications/{}/loadBalancers'.format(self.TEST_APP)) .EXPECT( ov_factory.value_list_contains(jp.DICT_MATCHES({ 'name': jp.STR_EQ(name), 'kind': jp.STR_EQ(kind), 'account': jp.STR_EQ(account), 'cloudProvider': jp.STR_EQ('kubernetes'), 'serverGroups': jp.LIST_MATCHES([ jp.DICT_MATCHES({ 'account': jp.STR_EQ(account), 'name': jp.STR_SUBSTR(self.TEST_APP), }), ]), })) )) return st.OperationContract( NoOpOperation('Has recorded a load balancer'), contract=builder.build())