def __log_api_diff(self, api_diff): text_list = [] for api, diff in api_diff.items(): added = diff.to_instances_added() removed = diff.to_instances_removed() if not (added or removed): continue text_list.append(api + " Changes:") if added: text_list.append("+ ADDED:") for resource, instances in added.items(): text_list.append(" %s" % resource) text_list.extend( [" - {!r}".format(name) for name in instances]) if removed: text_list.append("- REMOVED:") for resource, instances in removed.items(): text_list.append(" %s" % resource) text_list.extend( [" - {!r}".format(name) for name in instances]) self.__to_log_path( "--- RESOURCES ---", detail="\n".join(text_list) if text_list else "None", indent=2, ) if text_list: JournalLogger.journal_or_log_detail("GCP Resource Impact", "\n".join(text_list), format="pre") else: logging.info("No GCP resource impact")
def new_native_instance(cls, name, status_factory, base_url): """Create a new Spinnaker HttpAgent talking to the specified server port. Args: name: [string] The name of agent we are creating for reporting only. status_factory: [SpinnakerStatus (SpinnakerAgent, HttpResponseType)] Factory method for creating specialized SpinnakerStatus instances. base_url: [string] The service base URL to send messages to. Returns: A SpinnakerAgent connected to the specified instance port. """ logger = logging.getLogger(__name__) logger.info('Locating %s...', name) if not base_url: logger.error('Could not locate %s.', name) return None logger.info('%s is available at %s', name, base_url) env_url = os.path.join(base_url, 'resolvedEnv') deployed_config = scrape_spring_config(env_url) JournalLogger.journal_or_log_detail( '{0} configuration'.format(name), deployed_config) spinnaker_agent = cls(base_url, status_factory) spinnaker_agent.__deployed_config = deployed_config return spinnaker_agent
def new_native_instance(cls, name, status_factory, base_url): """Create a new Spinnaker HttpAgent talking to the specified server port. Args: name: [string] The name of agent we are creating for reporting only. status_factory: [SpinnakerStatus (SpinnakerAgent, HttpResponseType)] Factory method for creating specialized SpinnakerStatus instances. base_url: [string] The service base URL to send messages to. Returns: A SpinnakerAgent connected to the specified instance port. """ logger = logging.getLogger(__name__) logger.info('Locating %s...', name) if not base_url: logger.error('Could not locate %s.', name) return None logger.info('%s is available at %s', name, base_url) env_url = os.path.join(base_url, 'resolvedEnv') deployed_config = scrape_spring_config(env_url) JournalLogger.journal_or_log_detail( '{0} configuration'.format(name), deployed_config) spinnaker_agent = cls(base_url, status_factory) spinnaker_agent.__deployed_config = deployed_config return spinnaker_agent
def __log_api_diff(self, api_diff): text_list = [] for api, diff in api_diff.items(): added = diff.to_instances_added() removed = diff.to_instances_removed() if not (added or removed): continue text_list.append(api + ' Changes:') if added: text_list.append('+ ADDED:') for resource, instances in added.items(): text_list.append(' %s' % resource) text_list.extend([' - {!r}'.format(name) for name in instances]) if removed: text_list.append('- REMOVED:') for resource, instances in removed.items(): text_list.append(' %s' % resource) text_list.extend([' - {!r}'.format(name) for name in instances]) self.__to_log_path('--- RESOURCES ---', detail='\n'.join(text_list) if text_list else 'None', indent=2) if text_list: JournalLogger.journal_or_log_detail( 'GCP Resource Impact', '\n'.join(text_list), format='pre') else: logging.info('No GCP resource impact')
def __log_delta_quota(self, before, after): if before == after: logging.info("No GCP quota impact.") return diff = {} for region in after.keys(): before_quota = before.get(region, {}) after_quota = after.get(region, {}) if before_quota == after_quota: continue delta = { metric: after_quota[metric] - before_quota[metric] for metric in after_quota.keys() if after_quota.get(metric) != before_quota.get(metric) } if delta: diff[region] = delta self.__update_running_quota(diff) self.__to_log_path( "--- QUOTA ---", detail=json.JSONEncoder(indent=2, separators=(",", ": ")).encode(diff), indent=2, ) JournalLogger.journal_or_log_detail("GCP Quota Impact", str(diff), format="json")
def __log_api_diff(self, api_diff): text_list = [] for api, diff in api_diff.items(): added = diff.to_instances_added() removed = diff.to_instances_removed() if not (added or removed): continue text_list.append(api + ' Changes:') if added: text_list.append('+ ADDED:') for resource, instances in added.items(): text_list.append(' %s' % resource) text_list.extend([' - {!r}'.format(name) for name in instances]) if removed: text_list.append('- REMOVED:') for resource, instances in removed.items(): text_list.append(' %s' % resource) text_list.extend([' - {!r}'.format(name) for name in instances]) self.__to_log_path('--- RESOURCES ---', detail='\n'.join(text_list) if text_list else 'None', indent=2) if text_list: JournalLogger.journal_or_log_detail( 'GCP Resource Impact', '\n'.join(text_list), format='pre') else: logging.info('No GCP resource impact')
def new_gce_instance_from_bindings( cls, name, status_factory, bindings, port): """Create a new Spinnaker HttpAgent talking to the specified server port. Args: name: [string] The name of agent we are creating for reporting only. status_factory: [SpinnakerStatus (SpinnakerAgent, HttpResponseType)] Factory method for creating specialized SpinnakerStatus instances. bindings: [dict] List of bindings to configure the endpoint GCE_PROJECT: The GCE project ID that the endpoint is in. GCE_ZONE: The GCE zone that the endpoint is in. GCE_INSTANCE: The GCE instance that the endpoint is in. GCE_SSH_PASSPHRASE_FILE: If not empty, the SSH passphrase key for tunneling if needed to connect through a GCE firewall. GCE_SERVICE_ACCOUNT: If not empty, the GCE service account to use when interacting with the GCE instance. port: [int] The port of the endpoint we want to connect to. Returns: A SpinnakerAgent connected to the specified instance port. """ project = bindings['GCE_PROJECT'] zone = bindings['GCE_ZONE'] instance = bindings['GCE_INSTANCE'] ssh_passphrase_file = bindings.get('GCE_SSH_PASSPHRASE_FILE', None) service_account = bindings.get('GCE_SERVICE_ACCOUNT', None) logger = logging.getLogger(__name__) JournalLogger.begin_context('Locating {0}...'.format(name)) context_relation = 'ERROR' try: gcloud = gcp.GCloudAgent( project=project, zone=zone, service_account=service_account, ssh_passphrase_file=ssh_passphrase_file) netloc = gce_util.establish_network_connectivity( gcloud=gcloud, instance=instance, target_port=port) if not netloc: error = 'Could not locate {0}.'.format(name) logger.error(error) context_relation = 'INVALID' raise RuntimeError(error) protocol = bindings['NETWORK_PROTOCOL'] base_url = '{protocol}://{netloc}'.format(protocol=protocol, netloc=netloc) logger.info('%s is available at %s. Using %s', name, netloc, base_url) deployed_config = scrape_spring_config( os.path.join(base_url, 'resolvedEnv')) JournalLogger.journal_or_log_detail( '{0} configuration'.format(name), deployed_config) spinnaker_agent = cls(base_url, status_factory) spinnaker_agent.__deployed_config = deployed_config context_relation = 'VALID' except: logger.exception('Failed to create spinnaker agent.') raise finally: JournalLogger.end_context(relation=context_relation) return spinnaker_agent
def run(self, args, trace=True, output_scrubber=None): """Run the specified command. Args: args: The list of command-line arguments for self.__program. trace: If True then we should trace the call/response. Returns: CliResponseType tuple containing program execution results. """ command = self._args_to_full_commandline(args) log_msg = 'spawn {0} "{1}"'.format(command[0], '" "'.join(command[1:])) JournalLogger.journal_or_log(log_msg, _module=self.logger.name, _alwayslog=trace, _context='request') process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) stdout, stderr = process.communicate() scrubber = output_scrubber or self.__output_scrubber if scrubber: log_msg = 'Scrubbing output with {0}'.format( scrubber.__class__.__name__) JournalLogger.journal_or_log(log_msg, _module=self.logger.name, _alwayslog=trace) stdout = scrubber(stdout) # Strip leading/trailing eolns that program may add to errors and output. stderr = stderr.strip() stdout = stdout.strip() code = process.returncode # Always log to journal if stdout and stderr: which = 'both stdout and stderr' output_json = {'stdout': stdout, 'stderr': stderr} else: which = 'stderr' if stderr else 'stdout' output_json = stderr if stderr else stdout if output_json: JournalLogger.journal_or_log_detail('Result Code {0} / {1}'.format( code, which), output_json, _module=self.logger.name, _alwayslog=trace, _context='response') else: JournalLogger.journal_or_log( 'Result Code {0} / no ouptut'.format(code), _module=self.logger.name, _alwayslog=trace, _context='response') return CliResponseType(code, stdout, stderr)
def new_gce_instance_from_bindings( cls, name, status_factory, bindings, port): """Create a new Spinnaker HttpAgent talking to the specified server port. Args: name: [string] The name of agent we are creating for reporting only. status_factory: [SpinnakerStatus (SpinnakerAgent, HttpResponseType)] Factory method for creating specialized SpinnakerStatus instances. bindings: [dict] List of bindings to configure the endpoint GCE_PROJECT: The GCE project ID that the endpoint is in. GCE_ZONE: The GCE zone that the endpoint is in. GCE_INSTANCE: The GCE instance that the endpoint is in. GCE_SSH_PASSPHRASE_FILE: If not empty, the SSH passphrase key for tunneling if needed to connect through a GCE firewall. GCE_SERVICE_ACCOUNT: If not empty, the GCE service account to use when interacting with the GCE instance. port: [int] The port of the endpoint we want to connect to. Returns: A SpinnakerAgent connected to the specified instance port. """ project = bindings['GCE_PROJECT'] zone = bindings['GCE_ZONE'] instance = bindings['GCE_INSTANCE'] ssh_passphrase_file = bindings.get('GCE_SSH_PASSPHRASE_FILE', None) service_account = bindings.get('GCE_SERVICE_ACCOUNT', None) logger = logging.getLogger(__name__) JournalLogger.begin_context('Locating {0}...'.format(name)) context_relation = 'ERROR' try: gcloud = gcp.GCloudAgent( project=project, zone=zone, service_account=service_account, ssh_passphrase_file=ssh_passphrase_file) netloc = gce_util.establish_network_connectivity( gcloud=gcloud, instance=instance, target_port=port) if not netloc: error = 'Could not locate {0}.'.format(name) logger.error(error) context_relation = 'INVALID' raise RuntimeError(error) protocol = bindings['NETWORK_PROTOCOL'] base_url = '{protocol}://{netloc}'.format(protocol=protocol, netloc=netloc) logger.info('%s is available at %s. Using %s', name, netloc, base_url) deployed_config = scrape_spring_config( os.path.join(base_url, 'resolvedEnv')) JournalLogger.journal_or_log_detail( '{0} configuration'.format(name), deployed_config) spinnaker_agent = cls(base_url, status_factory) spinnaker_agent.__deployed_config = deployed_config context_relation = 'VALID' except: logger.exception('Failed to create spinnaker agent.') raise finally: JournalLogger.end_context(relation=context_relation) return spinnaker_agent
def run(self, args, output_scrubber=None): """Run the specified command. Args: args: The list of command-line arguments for self.__program. Returns: CliResponseType tuple containing program execution results. """ command = self._args_to_full_commandline(args) log_msg = 'spawn {0} "{1}"'.format(command[0], '" "'.join(command[1:])) JournalLogger.journal_or_log(log_msg, _logger=self.logger, _context='request') process = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) stdout, stderr = process.communicate() if stdout is not None: stdout = bytes.decode(stdout) if stderr is not None: stderr = bytes.decode(stderr) scrubber = output_scrubber or self.__output_scrubber if scrubber: log_msg = 'Scrubbing output with {0}'.format(scrubber.__class__.__name__) JournalLogger.journal_or_log(log_msg, _logger=self.logger) stdout = scrubber(stdout) # Strip leading/trailing eolns that program may add to errors and output. stderr = stderr.strip() stdout = stdout.strip() code = process.returncode # Always log to journal if stdout and stderr: which = 'both stdout and stderr' output_json = {'stdout':stdout, 'stderr':stderr} else: which = 'stderr' if stderr else 'stdout' output_json = stderr if stderr else stdout if output_json: JournalLogger.journal_or_log_detail( 'Result Code {0} / {1}'.format(code, which), output_json, _logger=self.logger, _context='response') else: JournalLogger.journal_or_log( 'Result Code {0} / no ouptut'.format(code), _logger=self.logger, _context='response') return CliResponseType(code, stdout, stderr)
def new_native_instance(cls, name, status_factory, base_url, bindings): """Create a new Spinnaker HttpAgent talking to the specified server port. Args: name: [string] The name of agent we are creating for reporting only. status_factory: [SpinnakerStatus (SpinnakerAgent, HttpResponseType)] Factory method for creating specialized SpinnakerStatus instances. base_url: [string] The service base URL to send messages to. bindings: [dict] List of bindings to configure the endpoint BEARER_AUTH_TOKEN: The token used to authenticate request to a protected host. IGNORE_SSL_CERT_VERIFICATION: If True, ignores SSL certificate verification when making requests. Returns: A SpinnakerAgent connected to the specified instance port. """ bearer_auth_token = bindings.get("BEARER_AUTH_TOKEN", None) ignore_ssl_cert_verification = bindings["IGNORE_SSL_CERT_VERIFICATION"] logger = logging.getLogger(__name__) logger.info("Locating %s...", name) if not base_url: logger.error("Could not locate %s.", name) return None logger.info("%s is available at %s", name, base_url) env_url = os.path.join(base_url, "resolvedEnv") headers = {} if bearer_auth_token: headers["Authorization"] = "Bearer {}".format(bearer_auth_token) deployed_config = scrape_spring_config( env_url, headers=headers, ignore_ssl_cert_verification=ignore_ssl_cert_verification, ) JournalLogger.journal_or_log_detail( "{0} configuration".format(name), deployed_config ) spinnaker_agent = cls(base_url, status_factory) spinnaker_agent.ignore_ssl_cert_verification = ignore_ssl_cert_verification spinnaker_agent.__deployed_config = deployed_config if bearer_auth_token: spinnaker_agent.add_header( "Authorization", "Bearer {}".format(bearer_auth_token) ) return spinnaker_agent
def new_native_instance(cls, name, status_factory, base_url, bindings): """Create a new Spinnaker HttpAgent talking to the specified server port. Args: name: [string] The name of agent we are creating for reporting only. status_factory: [SpinnakerStatus (SpinnakerAgent, HttpResponseType)] Factory method for creating specialized SpinnakerStatus instances. base_url: [string] The service base URL to send messages to. bindings: [dict] List of bindings to configure the endpoint BEARER_AUTH_TOKEN: The token used to authenticate request to a protected host. IGNORE_SSL_CERT_VERIFICATION: If True, ignores SSL certificate verification when making requests. Returns: A SpinnakerAgent connected to the specified instance port. """ bearer_auth_token = bindings.get('BEARER_AUTH_TOKEN', None) ignore_ssl_cert_verification = bindings['IGNORE_SSL_CERT_VERIFICATION'] logger = logging.getLogger(__name__) logger.info('Locating %s...', name) if not base_url: logger.error('Could not locate %s.', name) return None logger.info('%s is available at %s', name, base_url) env_url = os.path.join(base_url, 'resolvedEnv') headers = {} if bearer_auth_token: headers['Authorization'] = 'Bearer {}'.format(bearer_auth_token) deployed_config = scrape_spring_config(env_url, headers=headers, ignore_ssl_cert_verification=ignore_ssl_cert_verification) JournalLogger.journal_or_log_detail( '{0} configuration'.format(name), deployed_config) spinnaker_agent = cls(base_url, status_factory) spinnaker_agent.ignore_ssl_cert_verification = ignore_ssl_cert_verification spinnaker_agent.__deployed_config = deployed_config if bearer_auth_token: spinnaker_agent.add_header('Authorization', 'Bearer {}'.format(bearer_auth_token)) return spinnaker_agent
def new_native_instance(cls, name, status_factory, base_url, bindings): """Create a new Spinnaker HttpAgent talking to the specified server port. Args: name: [string] The name of agent we are creating for reporting only. status_factory: [SpinnakerStatus (SpinnakerAgent, HttpResponseType)] Factory method for creating specialized SpinnakerStatus instances. base_url: [string] The service base URL to send messages to. bindings: [dict] List of bindings to configure the endpoint BEARER_AUTH_TOKEN: The token used to authenticate request to a protected host. Returns: A SpinnakerAgent connected to the specified instance port. """ bearer_auth_token = bindings.get('BEARER_AUTH_TOKEN', None) logger = logging.getLogger(__name__) logger.info('Locating %s...', name) if not base_url: logger.error('Could not locate %s.', name) return None logger.info('%s is available at %s', name, base_url) env_url = os.path.join(base_url, 'resolvedEnv') deployed_config = scrape_spring_config(env_url, headers={ 'Authorization': 'Bearer {}'.format(bearer_auth_token) }) JournalLogger.journal_or_log_detail( '{0} configuration'.format(name), deployed_config) spinnaker_agent = cls(base_url, status_factory) spinnaker_agent.__deployed_config = deployed_config if bearer_auth_token: spinnaker_agent.add_header('Authorization', 'Bearer {}'.format(bearer_auth_token)) return spinnaker_agent
def __log_delta_quota(self, before, after): if before == after: logging.info('No GCP quota impact.') return diff = {} for region in after.keys(): before_quota = before.get(region, {}) after_quota = after.get(region, {}) if before_quota == after_quota: continue delta = {metric: after_quota[metric] - before_quota[metric] for metric in after_quota.keys() if after_quota.get(metric) != before_quota.get(metric)} if delta: diff[region] = delta self.__update_running_quota(diff) self.__to_log_path( '--- QUOTA ---', detail=json.JSONEncoder(indent=2, separators=(',', ': ')).encode(diff), indent=2) JournalLogger.journal_or_log_detail('GCP Quota Impact', str(diff), format='json')
def __send_http_request(self, path, http_type, data=None, headers=None): """Send an HTTP message. Args: path: [string] The URL path to send to (without network location) http_type: [string] The HTTP message type (e.g. POST) data: [string] Data payload to send, if any. headers: [dict] Headers to write, if any. Returns: HttpResponseType """ if headers is None: all_headers = self.__headers else: all_headers = self.__headers.copy() all_headers.update(headers) if path[0] == '/': path = path[1:] url = '{0}/{1}'.format(self.__base_url, path) req = urllib2.Request(url=url, data=data, headers=all_headers) req.get_method = lambda: http_type scrubbed_url = self.__http_scrubber.scrub_url(url) scrubbed_data = self.__http_scrubber.scrub_request(data) if data is not None: JournalLogger.journal_or_log_detail('{type} {url}'.format( type=http_type, url=scrubbed_url), scrubbed_data, _logger=self.logger, _context='request') else: JournalLogger.journal_or_log('{type} {url}'.format( type=http_type, url=scrubbed_url), _logger=self.logger, _context='request') code = None output = None exception = None try: response = urllib2.urlopen(req) code = response.getcode() output = response.read() scrubbed_output = self.__http_scrubber.scrub_response(output) JournalLogger.journal_or_log_detail( 'HTTP {code}'.format(code=code), scrubbed_output, _logger=self.logger, _context='response') except urllib2.HTTPError as ex: code = ex.getcode() output = ex.read() scrubbed_error = self.__http_scrubber.scrub_response(output) JournalLogger.journal_or_log_detail( 'HTTP {code}'.format(code=code), scrubbed_error, _logger=self.logger, _context='response') except urllib2.URLError as ex: JournalLogger.journal_or_log( 'Caught exception: {ex}\n{stack}'.format( ex=ex, stack=traceback.format_exc()), _logger=self.logger) exception = ex return HttpResponseType(code, output, exception)
def __send_http_request(self, path, http_type, data=None, headers=None): """Send an HTTP message. Args: path: [string] The URL path to send to (without network location) http_type: [string] The HTTP message type (e.g. POST) data: [string] Data payload to send, if any. headers: [dict] Headers to write, if any. Returns: HttpResponseType """ if headers is None: all_headers = self.__headers else: all_headers = self.__headers.copy() all_headers.update(headers) if path[0] == '/': path = path[1:] url = '{0}/{1}'.format(self.__base_url, path) encoded_data = str.encode(data) if data is not None else None req = Request(url=url, data=encoded_data, headers=all_headers) req.get_method = lambda: http_type scrubbed_url = self.__http_scrubber.scrub_url(url) scrubbed_data = self.__http_scrubber.scrub_request(data) if data is not None: JournalLogger.journal_or_log_detail( '{type} {url}'.format(type=http_type, url=scrubbed_url), scrubbed_data, _logger=self.logger, _context='request') else: JournalLogger.journal_or_log( '{type} {url}'.format(type=http_type, url=scrubbed_url), _logger=self.logger, _context='request') if self.__ignore_ssl_cert_verification: context = ssl._create_unverified_context() opener = build_opener(HTTPSHandler(context=context), HTTPCookieProcessor()) else: opener = build_opener(HTTPCookieProcessor()) code = None output = None exception = None headers = None try: response = opener.open(req) code = response.getcode() output = bytes.decode(response.read()) if sys.version_info[0] > 2: headers = dict(response.headers.items()) else: headers = response.info().headers scrubbed_output = self.__http_scrubber.scrub_response(output) JournalLogger.journal_or_log_detail( 'HTTP {code}'.format(code=code), scrubbed_output, _logger=self.logger, _context='response') except HTTPError as ex: code = ex.getcode() output = bytes.decode(ex.read()) scrubbed_error = self.__http_scrubber.scrub_response(output) JournalLogger.journal_or_log_detail( 'HTTP {code}'.format(code=code), scrubbed_error, _logger=self.logger, _context='response') except URLError as ex: JournalLogger.journal_or_log( 'Caught exception: {ex}\n{stack}'.format( ex=ex, stack=traceback.format_exc()), _logger=self.logger) exception = ex return HttpResponseType(http_code=code, output=output, exception=exception, headers=headers)
def __send_http_request(self, path, http_type, data=None, headers=None): """Send an HTTP message. Args: path: [string] The URL path to send to (without network location) http_type: [string] The HTTP message type (e.g. POST) data: [string] Data payload to send, if any. headers: [dict] Headers to write, if any. Returns: HttpResponseType """ if headers is None: all_headers = self.__headers else: all_headers = self.__headers.copy() all_headers.update(headers) if path[0] == '/': path = path[1:] url = '{0}/{1}'.format(self.__base_url, path) encoded_data = str.encode(data) if data is not None else None req = Request(url=url, data=encoded_data, headers=all_headers) req.get_method = lambda: http_type scrubbed_url = self.__http_scrubber.scrub_url(url) scrubbed_data = self.__http_scrubber.scrub_request(data) if data is not None: JournalLogger.journal_or_log_detail( '{type} {url}'.format(type=http_type, url=scrubbed_url), scrubbed_data, _logger=self.logger, _context='request') else: JournalLogger.journal_or_log( '{type} {url}'.format(type=http_type, url=scrubbed_url), _logger=self.logger, _context='request') if self.__ignore_ssl_cert_verification: context = ssl._create_unverified_context() opener = build_opener(HTTPSHandler(context=context), HTTPCookieProcessor()) else: opener = build_opener(HTTPCookieProcessor()) code = None output = None exception = None headers = None try: response = opener.open(req) code = response.getcode() output = bytes.decode(response.read()) if sys.version_info[0] > 2: headers = dict(response.headers.items()) else: headers = response.info().headers scrubbed_output = self.__http_scrubber.scrub_response(output) JournalLogger.journal_or_log_detail( 'HTTP {code}'.format(code=code), scrubbed_output, _logger=self.logger, _context='response') except HTTPError as ex: code = ex.getcode() output = bytes.decode(ex.read()) scrubbed_error = self.__http_scrubber.scrub_response(output) JournalLogger.journal_or_log_detail( 'HTTP {code}'.format(code=code), scrubbed_error, _logger=self.logger, _context='response') except URLError as ex: JournalLogger.journal_or_log( 'Caught exception: {ex}\n{stack}'.format( ex=ex, stack=traceback.format_exc()), _logger=self.logger) exception = ex return HttpResponseType(http_code=code, output=output, exception=exception, headers=headers)
def new_gce_instance_from_bindings(cls, name, status_factory, bindings, port): """Create a new Spinnaker HttpAgent talking to the specified server port. Args: name: [string] The name of agent we are creating for reporting only. status_factory: [SpinnakerStatus (SpinnakerAgent, HttpResponseType)] Factory method for creating specialized SpinnakerStatus instances. bindings: [dict] List of bindings to configure the endpoint GCE_PROJECT: The GCE project ID that the endpoint is in. GCE_ZONE: The GCE zone that the endpoint is in. GCE_INSTANCE: The GCE instance that the endpoint is in. GCE_SSH_PASSPHRASE_FILE: If not empty, the SSH passphrase key for tunneling if needed to connect through a GCE firewall. GCE_SERVICE_ACCOUNT: If not empty, the GCE service account to use when interacting with the GCE instance. IGNORE_SSL_CERT_VERIFICATION: If True, ignores SSL certificate verification when scraping spring config. port: [int] The port of the endpoint we want to connect to. Returns: A SpinnakerAgent connected to the specified instance port. """ project = bindings["GCE_PROJECT"] zone = bindings["GCE_ZONE"] instance = bindings["GCE_INSTANCE"] ssh_passphrase_file = bindings.get("GCE_SSH_PASSPHRASE_FILE", None) service_account = bindings.get("GCE_SERVICE_ACCOUNT", None) ignore_ssl_cert_verification = bindings["IGNORE_SSL_CERT_VERIFICATION"] logger = logging.getLogger(__name__) JournalLogger.begin_context("Locating {0}...".format(name)) context_relation = "ERROR" try: gcloud = gcp.GCloudAgent( project=project, zone=zone, service_account=service_account, ssh_passphrase_file=ssh_passphrase_file, ) netloc = gce_util.establish_network_connectivity( gcloud=gcloud, instance=instance, target_port=port ) if not netloc: error = "Could not locate {0}.".format(name) logger.error(error) context_relation = "INVALID" raise RuntimeError(error) protocol = bindings["NETWORK_PROTOCOL"] base_url = "{protocol}://{netloc}".format(protocol=protocol, netloc=netloc) logger.info("%s is available at %s. Using %s", name, netloc, base_url) deployed_config = scrape_spring_config( os.path.join(base_url, "resolvedEnv"), ignore_ssl_cert_verification=ignore_ssl_cert_verification, ) JournalLogger.journal_or_log_detail( "{0} configuration".format(name), deployed_config ) spinnaker_agent = cls(base_url, status_factory) spinnaker_agent.__deployed_config = deployed_config context_relation = "VALID" except: logger.exception("Failed to create spinnaker agent.") raise finally: JournalLogger.end_context(relation=context_relation) return spinnaker_agent
def __send_http_request(self, path, http_type, data=None, headers=None): """Send an HTTP message. Args: path: [string] The URL path to send to (without network location) http_type: [string] The HTTP message type (e.g. POST) data: [string] Data payload to send, if any. headers: [dict] Headers to write, if any. Returns: HttpResponseType """ if headers is None: all_headers = self.__headers else: all_headers = self.__headers.copy() all_headers.update(headers) if path[0] == '/': path = path[1:] url = '{0}/{1}'.format(self.__base_url, path) req = urllib2.Request(url=url, data=data, headers=all_headers) req.get_method = lambda: http_type scrubbed_url = self.__http_scrubber.scrub_url(url) scrubbed_data = self.__http_scrubber.scrub_request(data) if data is not None: JournalLogger.journal_or_log_detail( '{type} {url}'.format(type=http_type, url=scrubbed_url), scrubbed_data, _logger=self.logger, _context='request') else: JournalLogger.journal_or_log( '{type} {url}'.format(type=http_type, url=scrubbed_url), _logger=self.logger, _context='request') code = None output = None exception = None try: response = urllib2.urlopen(req) code = response.getcode() output = response.read() scrubbed_output = self.__http_scrubber.scrub_response(output) JournalLogger.journal_or_log_detail( 'HTTP {code}'.format(code=code), scrubbed_output, _logger=self.logger, _context='response') except urllib2.HTTPError as ex: code = ex.getcode() output = ex.read() scrubbed_error = self.__http_scrubber.scrub_response(output) JournalLogger.journal_or_log_detail( 'HTTP {code}'.format(code=code), scrubbed_error, _logger=self.logger, _context='response') except urllib2.URLError as ex: JournalLogger.journal_or_log( 'Caught exception: {ex}\n{stack}'.format( ex=ex, stack=traceback.format_exc()), _logger=self.logger) exception = ex return HttpResponseType(code, output, exception)