@ -19,6 +19,7 @@ import googleapiclient.discovery
import grpc
import logging
import os
import random
import shlex
import socket
import subprocess
@ -31,10 +32,20 @@ from oauth2client.client import GoogleCredentials
from src . proto . grpc . testing import messages_pb2
from src . proto . grpc . testing import test_pb2_grpc
logger = logging . getLogger ( __name__ )
logger = logging . getLogger ( )
console_handler = logging . StreamHandler ( )
logger . addHandler ( console_handler )
def parse_port_range ( port_arg ) :
try :
port = int ( port_arg )
return range ( port , port + 1 )
except :
port_min , port_max = port_arg . split ( ' : ' )
return range ( int ( port_min ) , int ( port_max ) + 1 )
argp = argparse . ArgumentParser ( description = ' Run xDS interop tests on GCP ' )
argp . add_argument ( ' --project_id ' , help = ' GCP project id ' )
argp . add_argument (
@ -75,10 +86,18 @@ argp.add_argument(
argp . add_argument ( ' --network ' ,
default = ' global/networks/default ' ,
help = ' GCP network to use ' )
argp . add_argument ( ' --grpc_port ' ,
default = 55551 ,
type = int ,
help = ' Listening port for created gRPC backends ' )
argp . add_argument ( ' --service_port_range ' ,
default = ' 8080:8180 ' ,
type = parse_port_range ,
help = ' Listening port for created gRPC backends. Specified as '
' either a single int or as a range in the format min:max, in '
' which case an available port p will be chosen s.t. min <= p '
' <= max ' )
argp . add_argument (
' --stats_port ' ,
default = 8079 ,
type = int ,
help = ' Local port for the client process to expose the LB stats service ' )
argp . add_argument ( ' --xds_server ' ,
default = ' trafficdirector.googleapis.com:443 ' ,
help = ' xDS server ' )
@ -119,8 +138,7 @@ TARGET_PROXY_NAME = 'test-target-proxy' + args.gcp_suffix
FORWARDING_RULE_NAME = ' test-forwarding-rule ' + args . gcp_suffix
KEEP_GCP_RESOURCES = args . keep_gcp_resources
TOLERATE_GCP_ERRORS = args . tolerate_gcp_errors
SERVICE_PORT = args . grpc_port
STATS_PORT = 55552
STATS_PORT = args . stats_port
INSTANCE_GROUP_SIZE = 2
WAIT_FOR_OPERATION_SEC = 60
NUM_TEST_RPCS = 10 * QPS
@ -209,7 +227,7 @@ def test_round_robin(backends, num_rpcs, stats_timeout_sec):
threshold , backend , stats )
def create_instance_template ( compute , name , grpc_port , projec t ) :
def create_instance_template ( compute , project , name , grpc_port ) :
config = {
' name ' : name ,
' properties ' : {
@ -262,8 +280,8 @@ nohup build/install/grpc-interop-testing/bin/xds-test-server --port=%d 1>/dev/nu
return result [ ' targetLink ' ]
def create_instance_group ( compute , name , size , grpc_port , template_url , projec t ,
zone ) :
def create_instance_group ( compute , project , zone , name , size , grpc_port ,
template_url ) :
config = {
' name ' : name ,
' instanceTemplate ' : template_url ,
@ -283,7 +301,7 @@ def create_instance_group(compute, name, size, grpc_port, template_url, project,
return result [ ' instanceGroup ' ]
def create_health_check ( compute , name , project ) :
def create_health_check ( compute , project , name ) :
config = {
' name ' : name ,
' type ' : ' TCP ' ,
@ -297,7 +315,7 @@ def create_health_check(compute, name, project):
return result [ ' targetLink ' ]
def create_health_check_firewall_rule ( compute , name , project ) :
def create_health_check_firewall_rule ( compute , project , name ) :
config = {
' name ' : name ,
' direction ' : ' INGRESS ' ,
@ -311,17 +329,13 @@ def create_health_check_firewall_rule(compute, name, project):
wait_for_global_operation ( compute , project , result [ ' name ' ] )
def create_backend_service ( compute , name , instance_group , health_check ,
project ) :
def create_backend_service ( compute , project , name , health_check ) :
config = {
' name ' : name ,
' loadBalancingScheme ' : ' INTERNAL_SELF_MANAGED ' ,
' healthChecks ' : [ health_check ] ,
' portName ' : ' grpc ' ,
' protocol ' : ' HTTP2 ' ,
' backends ' : [ {
' group ' : instance_group ,
} ]
' protocol ' : ' HTTP2 '
}
result = compute . backendServices ( ) . insert ( project = project ,
body = config ) . execute ( )
@ -329,7 +343,7 @@ def create_backend_service(compute, name, instance_group, health_check,
return result [ ' targetLink ' ]
def create_url_map ( compute , name , backend_service_url , host_name , project ) :
def create_url_map ( compute , project , name , backend_service_url , host_name ) :
path_matcher_name = ' path-matcher '
config = {
' name ' : name ,
@ -348,7 +362,7 @@ def create_url_map(compute, name, backend_service_url, host_name, project):
return result [ ' targetLink ' ]
def create_target_http_proxy ( compute , name , url_map_url , project ) :
def create_target_http_proxy ( compute , project , name , url_map_url ) :
config = {
' name ' : name ,
' url_map ' : url_map_url ,
@ -359,8 +373,8 @@ def create_target_http_proxy(compute, name, url_map_url, project):
return result [ ' targetLink ' ]
def create_global_forwarding_rule ( compute , name , grpc_port ,
target_http_proxy_url , project ) :
def create_global_forwarding_rule ( compute , project , name , grpc_port ,
target_http_proxy_url ) :
config = {
' name ' : name ,
' loadBalancingScheme ' : ' INTERNAL_SELF_MANAGED ' ,
@ -452,6 +466,18 @@ def delete_instance_template(compute, project, instance_template):
logger . info ( ' Delete failed: %s ' , http_error )
def add_instances_to_backend ( compute , project , backend_service , instance_group ) :
config = {
' backends ' : [ {
' group ' : instance_group ,
} ] ,
}
result = compute . backendServices ( ) . patch ( project = project ,
backendService = backend_service ,
body = config ) . execute ( )
wait_for_global_operation ( compute , project , result [ ' name ' ] )
def wait_for_global_operation ( compute ,
project ,
operation ,
@ -509,9 +535,9 @@ def wait_for_healthy_backends(compute, project_id, backend_service,
( timeout_sec , result ) )
def start_xds_client ( ) :
def start_xds_client ( service_port ) :
cmd = CLIENT_CMD . format ( service_host = SERVICE_HOST ,
service_port = SERVICE_PORT ,
service_port = service_port ,
stats_port = STATS_PORT ,
qps = QPS )
bootstrap_path = None
@ -534,33 +560,52 @@ if args.compute_discovery_document:
discovery_doc . read ( ) )
else :
compute = googleapiclient . discovery . build ( ' compute ' , ' v1 ' )
service_port = None
client_process = None
try :
instance_group_url = None
try :
template_url = create_instance_template ( compute , TEMPLATE_NAME ,
SERVICE_PORT , PROJECT_ID )
instance_group_url = create_instance_group ( compute , INSTANCE_GROUP_NAME ,
INSTANCE_GROUP_SIZE ,
SERVICE_PORT , template_url ,
PROJECT_ID , ZONE )
health_check_url = create_health_check ( compute , HEALTH_CHECK_NAME ,
PROJECT_ID )
create_health_check_firewall_rule ( compute , FIREWALL_RULE_NAME ,
PROJECT_ID )
backend_service_url = create_backend_service ( compute ,
health_check_url = create_health_check ( compute , PROJECT_ID ,
HEALTH_CHECK_NAME )
create_health_check_firewall_rule ( compute , PROJECT_ID ,
FIREWALL_RULE_NAME )
backend_service_url = create_backend_service ( compute , PROJECT_ID ,
BACKEND_SERVICE_NAME ,
instance_group_url ,
health_check_url ,
PROJECT_ID )
url_map_url = create_url_map ( compute , URL_MAP_NAME , backend_service_url ,
SERVICE_HOST , PROJECT_ID )
health_check_url )
url_map_url = create_url_map ( compute , PROJECT_ID , URL_MAP_NAME ,
backend_service_url , SERVICE_HOST )
target_http_proxy_url = create_target_http_proxy (
compute , TARGET_PROXY_NAME , url_map_url , PROJECT_ID )
create_global_forwarding_rule ( compute , FORWARDING_RULE_NAME ,
SERVICE_PORT , target_http_proxy_url ,
PROJECT_ID )
compute , PROJECT_ID , TARGET_PROXY_NAME , url_map_url )
potential_service_ports = list ( args . service_port_range )
random . shuffle ( potential_service_ports )
for port in potential_service_ports :
try :
create_global_forwarding_rule (
compute ,
PROJECT_ID ,
FORWARDING_RULE_NAME ,
port ,
target_http_proxy_url ,
)
service_port = port
break
except googleapiclient . errors . HttpError as http_error :
logger . warning (
' Got error %s when attempting to create forwarding rule to port %d . Retrying with another port. '
% ( http_error , port ) )
if not service_port :
raise Exception ( ' Failed to pick a service port in the range %s ' %
args . service_port_range )
template_url = create_instance_template ( compute , PROJECT_ID ,
TEMPLATE_NAME , service_port )
instance_group_url = create_instance_group ( compute , PROJECT_ID , ZONE ,
INSTANCE_GROUP_NAME ,
INSTANCE_GROUP_SIZE ,
service_port , template_url )
add_instances_to_backend ( compute , PROJECT_ID , BACKEND_SERVICE_NAME ,
instance_group_url )
except googleapiclient . errors . HttpError as http_error :
if TOLERATE_GCP_ERRORS :
logger . warning (
@ -595,7 +640,7 @@ try:
instance_name = item [ ' instance ' ] . split ( ' / ' ) [ - 1 ]
backends . append ( instance_name )
client_process = start_xds_client ( )
client_process = start_xds_client ( service_port )
if TEST_CASE == ' all ' :
test_ping_pong ( backends , NUM_TEST_RPCS , WAIT_FOR_STATS_SEC )