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)
def test_string_substr(self): context = ExecutionContext() substr_q = jp.STR_SUBSTR('q') substr_pqr = jp.STR_SUBSTR('pqr') self.assertGoodResult(PathValue('', 'pqr'), substr_q, substr_q(context, 'pqr')) self.assertGoodResult(PathValue('', 'rqp'), substr_q, substr_q(context, 'rqp')) self.assertGoodResult(PathValue('', 'pqr'), substr_pqr, substr_pqr(context, 'pqr')) self.assertBadResult(PathValue('', 'abc'), substr_q, substr_q(context, 'abc')) self.assertBadResult(PathValue('', 'xyz'), substr_q, substr_q(context, 'xyz'))
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['SPINNAKER_GOOGLE_ACCOUNT'] }) builder = gcp.GcpContractBuilder(self.gcp_observer) (builder.new_clause_builder( 'Instances in Target Pool', retryable_for_secs=15).list_resource('targetPools').EXPECT( ov_factory.value_list_contains( jp.DICT_MATCHES({ 'name': jp.STR_SUBSTR(self.__use_lb_tp_name), 'instances': jp.LIST_MATCHES([ jp.STR_SUBSTR(self.use_instance_names[0]), jp.STR_SUBSTR(self.use_instance_names[1]) ]) }))).AND( ov_factory.value_list_excludes( jp.DICT_MATCHES({ 'name': jp.STR_SUBSTR(self.__use_lb_tp_name), 'instances': jp.LIST_MATCHES([ jp.STR_SUBSTR(self.use_instance_names[2]) ]) })))) return st.OperationContract( self.new_post_operation(title='register_load_balancer_instances', data=payload, path='ops'), contract=builder.build())
def deployment_configmap_mounted_predicate(self, configmap_name): return ov_factory.value_list_contains( jp.DICT_MATCHES( { "spec": jp.DICT_MATCHES( { "template": jp.DICT_MATCHES( { "spec": jp.DICT_MATCHES( { "volumes": jp.LIST_MATCHES( [ jp.DICT_MATCHES( { "configMap": jp.DICT_MATCHES( { "name": jp.STR_SUBSTR( configmap_name ) } ) } ) ] ) } ) } ) } ), "status": jp.DICT_MATCHES({"availableReplicas": jp.NUM_GE(1)}), } ) )
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 upsert_google_server_group_tags(self): # pylint: disable=bad-continuation server_group_name = 'katotest-server-group' payload = self.agent.type_to_payload( 'upsertGoogleServerGroupTagsDescription', { 'credentials': self.bindings['SPINNAKER_GOOGLE_ACCOUNT'], 'zone': self.bindings['TEST_GCE_ZONE'], 'serverGroupName': 'katotest-server-group', 'tags': ['test-tag-1', 'test-tag-2'] }) builder = gcp.GcpContractBuilder(self.gcp_observer) (builder.new_clause_builder( 'Server Group Tags Added').inspect_resource( 'instanceGroupManagers', server_group_name).EXPECT( ov_factory.value_list_contains( jp.DICT_MATCHES({ 'name': jp.STR_SUBSTR(server_group_name), jp.build_path('tags', 'items'): jp.LIST_MATCHES(['test-tag-1', 'test-tag-2']) })))) return st.OperationContract(self.new_post_operation( title='upsert_server_group_tags', data=payload, path='ops'), contract=builder.build())
def upsert_google_server_group_tags(self): # pylint: disable=bad-continuation server_group_name = "katotest-server-group" payload = self.agent.type_to_payload( "upsertGoogleServerGroupTagsDescription", { "credentials": self.bindings["SPINNAKER_GOOGLE_ACCOUNT"], "zone": self.bindings["TEST_GCE_ZONE"], "serverGroupName": "katotest-server-group", "tags": ["test-tag-1", "test-tag-2"], }, ) builder = gcp.GcpContractBuilder(self.gcp_observer) (builder.new_clause_builder( "Server Group Tags Added").inspect_resource( "instanceGroupManagers", server_group_name).EXPECT( ov_factory.value_list_contains( jp.DICT_MATCHES({ "name": jp.STR_SUBSTR(server_group_name), jp.build_path("tags", "items"): jp.LIST_MATCHES(["test-tag-1", "test-tag-2"]), })))) return st.OperationContract( self.new_post_operation(title="upsert_server_group_tags", data=payload, path="ops"), contract=builder.build(), )
def destroy_server_group(self, version): serverGroupName = '%s-%s' % (self.__cluster_name, version) job = [{ 'cloudProvider': 'gce', 'asgName': serverGroupName, 'serverGroupName': serverGroupName, 'region': self.TEST_REGION, 'zone': self.TEST_ZONE, 'type': 'destroyServerGroup', 'regions': [self.TEST_REGION], 'zones': [self.TEST_ZONE], 'credentials': self.bindings['SPINNAKER_GOOGLE_ACCOUNT'], 'user': '******' }] job[0].update(self.__mig_payload_extra) builder = gcp.GcpContractBuilder(self.gcp_observer) (builder.new_clause_builder( self.__mig_title + ' Destroyed', retryable_for_secs=90).list_resource( self.__mig_manager_name, **self.__mig_manager_kwargs).EXPECT( ov_factory.value_list_path_excludes( 'baseInstanceName', jp.STR_SUBSTR(serverGroupName)))) payload = self.agent.make_json_payload_from_kwargs( job=job, description=self.__mig_title + ' Test - destroy server group', application=self.TEST_APP) return st.OperationContract(self.new_post_operation( title='destroy_server_group', data=payload, path=self.__path), 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_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 deployment_configmap_mounted_predicate(self, configmap_name): return ov_factory.value_list_contains( jp.DICT_MATCHES({ 'spec': jp.DICT_MATCHES({ 'template': jp.DICT_MATCHES({ 'spec': jp.DICT_MATCHES({ 'volumes': jp.LIST_MATCHES([ jp.DICT_MATCHES({ 'configMap': jp.DICT_MATCHES({ 'name': jp.STR_SUBSTR(configmap_name) }) }) ]) }) }) }), 'status': jp.DICT_MATCHES({'availableReplicas': jp.NUM_GE(1)}) }))
def delete_load_balancer(self): job = [{ "loadBalancerName": self.__lb_name, "networkLoadBalancerName": self.__lb_name, "region": self.TEST_REGION, "type": "deleteLoadBalancer", "regions": [self.TEST_REGION], "credentials": self.bindings['SPINNAKER_GOOGLE_ACCOUNT'], "cloudProvider": "gce", "user": "******" }] builder = gcp.GcpContractBuilder(self.gcp_observer) (builder.new_clause_builder( 'Load Balancer Created', retryable_for_secs=30).list_resource('forwardingRules').EXPECT( ov_factory.value_list_path_excludes( 'name', jp.STR_SUBSTR(self.__lb_name)))) payload = self.agent.make_json_payload_from_kwargs( job=job, description=self.__mig_title + ' Test - delete load balancer', application=self.TEST_APP) return st.OperationContract(self.new_post_operation( title='delete_load_balancer', data=payload, path=self.__path), contract=builder.build())
def delete_security_group(self): '''Deletes a security group. ''' bindings = self.bindings sec_group_payload = self.agent.make_json_payload_from_kwargs( job=[ { 'cloudProvider': 'gce', 'credentials': bindings['SPINNAKER_GOOGLE_ACCOUNT'], 'regions': ['global'], 'securityGroupName': self.__lb_name + '-rule', 'type': 'deleteSecurityGroup', 'user': '******' } ], description='Delete a Security Group.', application=self.TEST_APP ) builder = gcp.GcpContractBuilder(self.gcp_observer) (builder.new_clause_builder('Security Group Deleted', retryable_for_secs=30) .list_resource('firewalls') .EXPECT(ov_factory.value_list_path_excludes( 'name', jp.STR_SUBSTR(self.__lb_name + '-rule')))) return st.OperationContract( self.new_post_operation(title='delete security group', data=sec_group_payload, path='tasks'), contract=builder.build() )
def delete_security_group(self): """Deletes a security group.""" bindings = self.bindings sec_group_payload = self.agent.make_json_payload_from_kwargs( job=[ { "cloudProvider": "gce", "credentials": bindings["SPINNAKER_GOOGLE_ACCOUNT"], "regions": ["global"], "securityGroupName": self.__lb_name + "-rule", "type": "deleteSecurityGroup", "user": "******", } ], description="Delete a Security Group.", application=self.TEST_APP, ) builder = gcp.GcpContractBuilder(self.gcp_observer) ( builder.new_clause_builder("Security Group Deleted", retryable_for_secs=30) .list_resource("firewalls") .EXPECT( ov_factory.value_list_path_excludes( "name", jp.STR_SUBSTR(self.__lb_name + "-rule") ) ) ) return st.OperationContract( self.new_post_operation( title="delete security group", data=sec_group_payload, path="tasks" ), contract=builder.build(), )
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)
def deregister_load_balancer_instances(self): """Creates a test unregistering instances from load balancer. Returns: st.OperationContract """ # pylint: disable=bad-continuation payload = self.agent.type_to_payload( "deregisterInstancesFromGoogleLoadBalancerDescription", { "loadBalancerNames": [self.__use_lb_name], "instanceIds": self.use_instance_names[:2], "region": self.bindings["TEST_GCE_REGION"], "credentials": self.bindings["SPINNAKER_GOOGLE_ACCOUNT"], }, ) # NOTE(ewiseblatt): 20150530 # This displays an error that 'instances' field doesnt exist. # That's because it was removed because all the instances are gone. # I dont have a way to express that the field itself is optional, # just the record. Leaving it as is because displaying this type of # error is usually helpful for development. builder = gcp.GcpContractBuilder(self.gcp_observer) (builder.new_clause_builder( "Instances not in Target Pool", retryable_for_secs=30).list_resource( "targetPools", region=self.bindings["TEST_GCE_REGION"]).EXPECT( ov_factory.value_list_excludes( jp.DICT_MATCHES({ "name": jp.STR_SUBSTR(self.__use_lb_tp_name), "instances": jp.LIST_MATCHES([ jp.STR_SUBSTR(self.use_instance_names[0]), jp.STR_SUBSTR(self.use_instance_names[1]), ]), })))) return st.OperationContract( self.new_post_operation(title="deregister_load_balancer_instances", data=payload, path="ops"), contract=builder.build(), )
def upsert_load_balancer(self): self.__use_lb_name = 'katotest-lb-' + self.test_id self.__use_lb_hc_name = '%s-hc' % self.__use_lb_name self.__use_lb_tp_name = '%s-tp' % self.__use_lb_name self.__use_lb_target = '{0}/targetPools/{1}'.format( self.bindings['TEST_GCE_REGION'], self.__use_lb_tp_name) interval = 123 healthy = 4 unhealthy = 5 timeout = 78 path = '/' + self.__use_lb_target health_check = { 'checkIntervalSec': interval, 'healthyThreshold': healthy, 'unhealthyThreshold': unhealthy, 'timeoutSec': timeout, 'requestPath': path } # pylint: disable=bad-continuation payload = self.agent.type_to_payload( 'upsertGoogleLoadBalancerDescription', { 'healthCheck': health_check, 'region': self.bindings['TEST_GCE_REGION'], 'credentials': self.bindings['SPINNAKER_GOOGLE_ACCOUNT'], 'loadBalancerName': self.__use_lb_name }) builder = gcp.GcpContractBuilder(self.gcp_observer) (builder.new_clause_builder('Forwarding Rules Added', retryable_for_secs=30) .list_resource('forwardingRules') .contains_path_value('name', self.__use_lb_name) .contains_path_value('target', self.__use_lb_target)) (builder.new_clause_builder('Target Pool Added', retryable_for_secs=15) .list_resource('targetPools') .contains_path_value('name', self.__use_lb_tp_name)) # We list the resources here because the name isnt exact # and the list also returns the details we need. hc_dict = dict(health_check) del hc_dict['requestPath'] hc_match = {name: jp.NUM_EQ(value) for name, value in hc_dict.items()} hc_match['requestPath'] = jp.STR_EQ(path) hc_match['name'] = jp.STR_SUBSTR(self.__use_http_lb_hc_name) (builder.new_clause_builder('Health Check Added', retryable_for_secs=15) .list_resource('httpHealthChecks') .contains_match(hc_match)) return st.OperationContract( self.new_post_operation( title='upsert_load_balancer', data=payload, path='ops'), contract=builder.build())
def delete_server_group(self): """Creates OperationContract for deleteServerGroup. To verify the operation, we just check that the GCP managed instance group is no longer visible on GCP (or is in the process of terminating). """ bindings = self.bindings group_name = "{app}-{stack}-v000".format( app=self.TEST_APP, stack=bindings["TEST_STACK"] ) # TODO(ttomsu): Change this back from asgName to serverGroupName # once it is fixed in orca. payload = self.agent.make_json_payload_from_kwargs( job=[ { "cloudProvider": "gce", "serverGroupName": group_name, "region": bindings["TEST_GCE_REGION"], "zone": bindings["TEST_GCE_ZONE"], "asgName": group_name, "type": "destroyServerGroup", "regions": [bindings["TEST_GCE_REGION"]], "zones": [bindings["TEST_GCE_ZONE"]], "credentials": bindings["SPINNAKER_GOOGLE_ACCOUNT"], "user": "******", } ], application=self.TEST_APP, description="DestroyServerGroup: " + group_name, ) builder = gcp.GcpContractBuilder(self.gcp_observer) ( builder.new_clause_builder("Managed Instance Group Removed") .inspect_resource("instanceGroupManagers", group_name) .EXPECT( ov_factory.error_list_contains(gcp.HttpErrorPredicate(http_code=404)) ) .OR(ov_factory.value_list_path_contains("targetSize", jp.NUM_EQ(0))) ) ( builder.new_clause_builder("Instances Are Removed", retryable_for_secs=30) .list_resource("instances") .EXPECT( ov_factory.value_list_path_excludes("name", jp.STR_SUBSTR(group_name)) ) ) return st.OperationContract( self.new_post_operation( title="delete_server_group", data=payload, path="tasks" ), contract=builder.build(), )
def disable_server_group(self): job = [{ "cloudProvider": "gce", "asgName": self.__server_group_name, "serverGroupName": self.__server_group_name, "region": self.TEST_REGION, "zone": self.TEST_ZONE, "type": "disableServerGroup", "regions": [self.TEST_REGION], "zones": [self.TEST_ZONE], "credentials": self.bindings["SPINNAKER_GOOGLE_ACCOUNT"], "user": "******", }] job[0].update(self.__mig_payload_extra) builder = gcp.GcpContractBuilder(self.gcp_observer) (builder.new_clause_builder( self.__mig_title + " Disabled", retryable_for_secs=90).list_resource( self.__mig_manager_name, **self.__mig_manager_kwargs).EXPECT( ov_factory.value_list_path_contains( "baseInstanceName", jp.STR_SUBSTR(self.__server_group_name))).AND( ov_factory.value_list_excludes( jp.DICT_MATCHES({ "baseInstanceName": jp.STR_SUBSTR(self.__server_group_name), "targetPools": jp.LIST_MATCHES([jp.STR_SUBSTR("https")]), })))) payload = self.agent.make_json_payload_from_kwargs( job=job, description=self.__mig_title + " Test - disable server group", application=self.TEST_APP, ) return st.OperationContract( self.new_post_operation(title="disable_server_group", data=payload, path=self.__path), contract=builder.build(), )
def create_load_balancer(self): job = [{ "cloudProvider": "gce", "loadBalancerName": self.__lb_name, "ipProtocol": "TCP", "portRange": "8080", "provider": "gce", "stack": self.TEST_STACK, "detail": "frontend", "credentials": self.bindings["SPINNAKER_GOOGLE_ACCOUNT"], "region": self.TEST_REGION, "listeners": [{ "protocol": "TCP", "portRange": "8080", "healthCheck": False }], "name": self.__lb_name, "type": "upsertLoadBalancer", "availabilityZones": { self.TEST_REGION: [] }, "user": "******", }] builder = gcp.GcpContractBuilder(self.gcp_observer) (builder.new_clause_builder( "Load Balancer Created", retryable_for_secs=30).list_resource("forwardingRules").EXPECT( ov_factory.value_list_path_contains( "name", jp.STR_SUBSTR(self.__lb_name)))) payload = self.agent.make_json_payload_from_kwargs( job=job, description=self.__mig_title + " Test - create load balancer", application=self.TEST_APP, ) return st.OperationContract( self.new_post_operation(title="create_load_balancer", data=payload, path=self.__path), contract=builder.build(), )
def test_path_conjunction(self): context = ExecutionContext() text = 'x=X, a=A, b=B, z=Z' aA = jp.STR_SUBSTR('a=A') bB = jp.STR_SUBSTR('b=B') conjunction = jp.AND([aA, bB]) pred = PathPredicate('value', conjunction) source = {'value': text, 'wrong': 'a=A', 'another': 'b=B'} conjunction_result = conjunction(context, text) builder = PathPredicateResultBuilder(source, pred) builder.add_result_candidate( PathValue('value', text), conjunction_result.clone_with_source(source=source, base_target_path='value', base_value_path='value')) expect = builder.build(True) pred_result = pred(context, source) self.assertEqual(expect, pred_result)
def deregister_load_balancer_instances(self): """Creates a test unregistering instances from load balancer. Returns: st.OperationContract """ # pylint: disable=bad-continuation payload = self.agent.type_to_payload( 'deregisterInstancesFromGoogleLoadBalancerDescription', { 'loadBalancerNames': [self.__use_lb_name], 'instanceIds': self.use_instance_names[:2], 'region': self.bindings['TEST_GCE_REGION'], 'credentials': self.bindings['SPINNAKER_GOOGLE_ACCOUNT'] }) # NOTE(ewiseblatt): 20150530 # This displays an error that 'instances' field doesnt exist. # That's because it was removed because all the instances are gone. # I dont have a way to express that the field itself is optional, # just the record. Leaving it as is because displaying this type of # error is usually helpful for development. builder = gcp.GcpContractBuilder(self.gcp_observer) (builder.new_clause_builder( 'Instances not in Target Pool', retryable_for_secs=30).list_resource( 'targetPools', region=self.bindings['TEST_GCE_REGION']).excludes_match({ 'name': jp.STR_SUBSTR(self.__use_lb_tp_name), 'instances': jp.LIST_MATCHES([ jp.STR_SUBSTR(self.use_instance_names[0]), jp.STR_SUBSTR(self.use_instance_names[1]) ]) })) return st.OperationContract(self.new_post_operation( title='deregister_load_balancer_instances', data=payload, path='ops'), contract=builder.build())
def delete_load_balancer(self): """Creates OperationContract for deleteLoadBalancer. To verify the operation, we just check that the GCP resources created by upsert_load_balancer are no longer visible on GCP. """ bindings = self.bindings payload = self.agent.make_json_payload_from_kwargs( job=[{ 'type': 'deleteLoadBalancer', 'cloudProvider': 'gce', 'loadBalancerName': self.__lb_name, 'region': bindings['TEST_GCE_REGION'], 'regions': [bindings['TEST_GCE_REGION']], 'credentials': bindings['SPINNAKER_GOOGLE_ACCOUNT'], 'user': '******' }], description='Delete Load Balancer: {0} in {1}:{2}'.format( self.__lb_name, bindings['SPINNAKER_GOOGLE_ACCOUNT'], bindings['TEST_GCE_REGION']), application=self.TEST_APP) builder = gcp.GcpContractBuilder(self.gcp_observer) (builder.new_clause_builder( 'Health Check Removed', retryable_for_secs=30).list_resource('httpHealthChecks').EXPECT( ov_factory.value_list_path_excludes( 'name', jp.STR_SUBSTR('%s-hc' % self.__lb_name)))) (builder.new_clause_builder('TargetPool Removed').list_resource( 'targetPools').EXPECT( ov_factory.value_list_path_excludes( 'name', jp.STR_SUBSTR('%s-tp' % self.__lb_name)))) (builder.new_clause_builder('Forwarding Rule Removed').list_resource( 'forwardingRules').EXPECT( ov_factory.value_list_path_excludes( 'name', jp.STR_SUBSTR(self.__lb_name)))) return st.OperationContract(self.new_post_operation( title='delete_load_balancer', data=payload, path='tasks'), contract=builder.build())
def create_load_balancer(self): job = [{ 'cloudProvider': 'gce', 'loadBalancerName': self.__lb_name, 'ipProtocol': 'TCP', 'portRange': '8080', 'provider': 'gce', 'stack': self.TEST_STACK, 'detail': 'frontend', 'credentials': self.bindings['SPINNAKER_GOOGLE_ACCOUNT'], 'region': self.TEST_REGION, 'listeners': [{ 'protocol': 'TCP', 'portRange': '8080', 'healthCheck': False }], 'name': self.__lb_name, 'type': 'upsertLoadBalancer', 'availabilityZones': { self.TEST_REGION: [] }, 'user': '******' }] builder = gcp.GcpContractBuilder(self.gcp_observer) (builder.new_clause_builder( 'Load Balancer Created', retryable_for_secs=30).list_resource('forwardingRules').EXPECT( ov_factory.value_list_path_contains( 'name', jp.STR_SUBSTR(self.__lb_name)))) payload = self.agent.make_json_payload_from_kwargs( job=job, description=self.__mig_title + ' Test - create load balancer', application=self.TEST_APP) return st.OperationContract(self.new_post_operation( title='create_load_balancer', data=payload, path=self.__path), contract=builder.build())
def delete_http_load_balancer(self): # pylint: disable=bad-continuation payload = self.agent.type_to_payload( "deleteGoogleHttpLoadBalancerDescription", { "loadBalancerName": self.__use_http_lb_name, "credentials": self.bindings["SPINNAKER_GOOGLE_ACCOUNT"], }, ) builder = gcp.GcpContractBuilder(self.gcp_observer) (builder.new_clause_builder("Health Check Removed").list_resource( "httpHealthChecks").EXPECT( ov_factory.value_list_path_excludes( "name", jp.STR_SUBSTR(self.__use_http_lb_hc_name)))) (builder.new_clause_builder("Global Forwarding Rules Removed"). list_resource("globalForwardingRules").EXPECT( ov_factory.value_list_path_excludes( "name", jp.STR_SUBSTR(self.__use_http_lb_fr_name)))) (builder.new_clause_builder("Backend Service Removed").list_resource( "backendServices").EXPECT( ov_factory.value_list_path_excludes( "name", jp.STR_SUBSTR(self.__use_http_lb_bs_name)))) (builder.new_clause_builder("Url Map Removed").list_resource( "urlMaps").EXPECT( ov_factory.value_list_path_excludes( "name", jp.STR_SUBSTR(self.__use_http_lb_map_name)))) (builder.new_clause_builder("Target Http Proxy Removed").list_resource( "targetHttpProxies").EXPECT( ov_factory.value_list_path_excludes( "name", jp.STR_SUBSTR(self.__use_http_lb_proxy_name)))) return st.OperationContract( self.new_post_operation(title="delete_http_load_balancer", data=payload, path="ops"), contract=builder.build(), )
def delete_http_load_balancer(self): '''Deletes the L7 LB. ''' bindings = self.bindings delete = copy.deepcopy(self.__proto_delete) payload = self.agent.make_json_payload_from_kwargs( job=[delete], description='Delete L7 Load Balancer: {0} in {1}'.format( self.__lb_name, bindings['SPINNAKER_GOOGLE_ACCOUNT'], ), application=self.TEST_APP ) contract_builder = gcp.GcpContractBuilder(self.gcp_observer) (contract_builder.new_clause_builder('Health Check Removed', retryable_for_secs=30) .list_resource('healthChecks') .EXPECT(ov_factory.value_list_path_excludes( 'name', jp.STR_SUBSTR(self.__proto_hc['name']))) ) (contract_builder.new_clause_builder('Url Map Removed', retryable_for_secs=30) .list_resource('urlMaps') .EXPECT(ov_factory.value_list_path_excludes( 'name', jp.STR_SUBSTR(self.__lb_name))) ) (contract_builder.new_clause_builder('Forwarding Rule Removed', retryable_for_secs=30) .list_resource('globalForwardingRules') .EXPECT(ov_factory.value_list_path_excludes( 'name', jp.STR_SUBSTR(self.__lb_name))) ) return st.OperationContract( self.new_post_operation( title='delete_http_load_balancer', data=payload, path='tasks'), contract=contract_builder.build())
def delete_server_group(self): """Creates OperationContract for deleteServerGroup. To verify the operation, we just check that the AWS Auto Scaling Group is no longer visible on AWS (or is in the process of terminating). """ bindings = self.bindings group_name = '{app}-{stack}-v000'.format( app=self.TEST_APP, stack=bindings['TEST_STACK']) payload = self.agent.make_json_payload_from_kwargs( job=[{ 'cloudProvider': 'aws', 'type': 'destroyServerGroup', 'serverGroupName': group_name, 'asgName': group_name, 'region': bindings['TEST_AWS_REGION'], 'regions': [bindings['TEST_AWS_REGION']], 'credentials': bindings['SPINNAKER_AWS_ACCOUNT'], 'user': '******' }], application=self.TEST_APP, description='DestroyServerGroup: ' + group_name) builder = aws.AwsPythonContractBuilder(self.aws_observer) (builder.new_clause_builder('Auto Scaling Group Removed') .call_method( self.autoscaling_client.describe_auto_scaling_groups, AutoScalingGroupNames=[group_name]) .EXPECT( ov_factory.error_list_contains( jp.ExceptionMatchesPredicate( (BotoCoreError, ClientError), 'AutoScalingGroupNotFound'))) .OR( ov_factory.value_list_path_contains( 'AutoScalingGroups', jp.LIST_MATCHES([]))) .OR( ov_factory.value_list_path_contains( 'AutoScalingGroups', jp.LIST_MATCHES([ jp.DICT_MATCHES({'Status': jp.STR_SUBSTR('Delete'), 'MaxSize': jp.NUM_EQ(0)})]))) ) return st.OperationContract( self.new_post_operation( title='delete_server_group', data=payload, path='tasks'), contract=builder.build())
def disable_server_group(self): job = [{ 'cloudProvider': 'gce', 'asgName': self.__server_group_name, 'serverGroupName': self.__server_group_name, 'region': self.TEST_REGION, 'zone': self.TEST_ZONE, 'type': 'disableServerGroup', 'regions': [self.TEST_REGION], 'zones': [self.TEST_ZONE], 'credentials': self.bindings['SPINNAKER_GOOGLE_ACCOUNT'], 'user': '******' }] job[0].update(self.__mig_payload_extra) builder = gcp.GcpContractBuilder(self.gcp_observer) (builder.new_clause_builder( self.__mig_title + ' Disabled', retryable_for_secs=90).list_resource( self.__mig_manager_name, **self.__mig_manager_kwargs).contains_path_value( 'baseInstanceName', self.__server_group_name).excludes_match({ 'baseInstanceName': jp.STR_SUBSTR(self.__server_group_name), 'targetPools': jp.LIST_MATCHES([jp.STR_SUBSTR('https')]) })) payload = self.agent.make_json_payload_from_kwargs( job=job, description=self.__mig_title + ' Test - disable server group', application=self.TEST_APP) return st.OperationContract(self.new_post_operation( title='disable_server_group', data=payload, path=self.__path), 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())