def _build_global_forwarding_rule_dict(params, project_id=None): """ Reformat services in Ansible Params. :param params: Params from AnsibleModule object :type params: ``dict`` :param project_id: The GCP project ID. :type project_id: ``str`` :return: dictionary suitable for submission to GCP API. :rtype ``dict`` """ url = '' if project_id: url = GCPUtils.build_googleapi_url(project_id) gcp_dict = GCPUtils.params_to_gcp_dict(params, 'forwarding_rule_name') if 'target' in gcp_dict: gcp_dict['target'] = '%s/global/targetHttpProxies/%s' % ( url, gcp_dict['target']) if 'address' in gcp_dict: gcp_dict['IPAddress'] = '%s/global/addresses/%s' % ( url, gcp_dict['address']) del gcp_dict['address'] if 'protocol' in gcp_dict: gcp_dict['IPProtocol'] = gcp_dict['protocol'] del gcp_dict['protocol'] return gcp_dict
def _build_url_map_dict(params, project_id=None): """ Reformat services in Ansible Params. :param params: Params from AnsibleModule object :type params: ``dict`` :param project_id: The GCP project ID. :type project_id: ``str`` :return: dictionary suitable for submission to GCP UrlMap API. :rtype ``dict`` """ url = '' if project_id: url = GCPUtils.build_googleapi_url(project_id) gcp_dict = GCPUtils.params_to_gcp_dict(params, 'url_map_name') if 'defaultService' in gcp_dict: gcp_dict['defaultService'] = '%s/global/backendServices/%s' % ( url, gcp_dict['defaultService']) if 'pathMatchers' in gcp_dict: gcp_dict['pathMatchers'] = _build_path_matchers( gcp_dict['pathMatchers'], project_id) return gcp_dict
def test_get_gcp_resource_from_methodId(self): input_data = 'compute.urlMaps.list' actual = GCPUtils.get_gcp_resource_from_methodId(input_data) self.assertEqual('urlMaps', actual) input_data = None actual = GCPUtils.get_gcp_resource_from_methodId(input_data) self.assertFalse(actual) input_data = 666 actual = GCPUtils.get_gcp_resource_from_methodId(input_data) self.assertFalse(actual)
def create_healthcheck(client, params, project_id, resource_type='HTTP'): """ Create a new Healthcheck. :param client: An initialized GCE Compute Discovery resource. :type client: :class: `googleapiclient.discovery.Resource` :param params: Dictionary of arguments from AnsibleModule. :type params: ``dict`` :return: Tuple with changed status and response dict :rtype: ``tuple`` in the format of (bool, dict) """ gcp_dict = _build_healthcheck_dict(params) try: resource, _ = _get_req_resource(client, resource_type) args = {'project': project_id, 'body': gcp_dict} req = resource.insert(**args) return_data = GCPUtils.execute_api_client_req(req, client, raw=False) if not return_data: return_data = get_healthcheck(client, name=params['healthcheck_name'], project_id=project_id) return (True, return_data) except Exception: raise
def _build_path_matchers(path_matcher_list, project_id): """ Reformat services in path matchers list. Specifically, builds out URLs. :param path_matcher_list: The GCP project ID. :type path_matcher_list: ``list`` of ``dict`` :param project_id: The GCP project ID. :type project_id: ``str`` :return: list suitable for submission to GCP UrlMap API Path Matchers list. :rtype ``list`` of ``dict`` """ url = '' if project_id: url = GCPUtils.build_googleapi_url(project_id) for pm in path_matcher_list: if 'defaultService' in pm: pm['defaultService'] = '%s/global/backendServices/%s' % ( url, pm['defaultService']) if 'pathRules' in pm: for rule in pm['pathRules']: if 'service' in rule: rule['service'] = '%s/global/backendServices/%s' % ( url, rule['service']) return path_matcher_list
def _build_healthcheck_dict(params): """ Reformat services in Ansible Params for GCP. :param params: Params from AnsibleModule object :type params: ``dict`` :param project_id: The GCP project ID. :type project_id: ``str`` :return: dictionary suitable for submission to GCP HealthCheck (HTTP/HTTPS) API. :rtype ``dict`` """ gcp_dict = GCPUtils.params_to_gcp_dict(params, 'healthcheck_name') if 'timeout' in gcp_dict: gcp_dict['timeoutSec'] = gcp_dict['timeout'] del gcp_dict['timeout'] if 'checkInterval' in gcp_dict: gcp_dict['checkIntervalSec'] = gcp_dict['checkInterval'] del gcp_dict['checkInterval'] if 'hostHeader' in gcp_dict: gcp_dict['host'] = gcp_dict['hostHeader'] del gcp_dict['hostHeader'] if 'healthcheckType' in gcp_dict: del gcp_dict['healthcheckType'] return gcp_dict
def create_global_forwarding_rule(client, params, project_id): """ Create a new Global Forwarding Rule. :param client: An initialized GCE Compute Discovery resource. :type client: :class: `googleapiclient.discovery.Resource` :param params: Dictionary of arguments from AnsibleModule. :type params: ``dict`` :return: Tuple with changed status and response dict :rtype: ``tuple`` in the format of (bool, dict) """ gcp_dict = _build_global_forwarding_rule_dict(params, project_id) try: req = client.globalForwardingRules().insert(project=project_id, body=gcp_dict) return_data = GCPUtils.execute_api_client_req(req, client, raw=False) if not return_data: return_data = get_global_forwarding_rule( client, name=params['forwarding_rule_name'], project_id=project_id) return (True, return_data) except Exception: raise
def test_filter_gcp_fields(self): input_data = { u'kind': u'compute#httpsHealthCheck', u'description': u'', u'timeoutSec': 5, u'checkIntervalSec': 5, u'port': 443, u'healthyThreshold': 2, u'host': u'', u'requestPath': u'/', u'unhealthyThreshold': 2, u'creationTimestamp': u'2017-05-16T15:09:36.546-07:00', u'id': u'8727093129334146639', u'selfLink': u'https://www.googleapis.com/compute/v1/projects/myproject/global/httpsHealthChecks/myhealthcheck', u'name': u'myhealthcheck' } expected = { 'name': 'myhealthcheck', 'checkIntervalSec': 5, 'port': 443, 'unhealthyThreshold': 2, 'healthyThreshold': 2, 'host': '', 'timeoutSec': 5, 'requestPath': '/' } actual = GCPUtils.filter_gcp_fields(input_data) self.assertEqual(expected, actual)
def test_get_entity_name_from_resource_name(self): input_data = 'urlMaps' actual = GCPUtils.get_entity_name_from_resource_name(input_data) self.assertEqual('urlMap', actual) input_data = 'targetHttpProxies' actual = GCPUtils.get_entity_name_from_resource_name(input_data) self.assertEqual('targetHttpProxy', actual) input_data = 'globalForwardingRules' actual = GCPUtils.get_entity_name_from_resource_name(input_data) self.assertEqual('forwardingRule', actual) input_data = '' actual = GCPUtils.get_entity_name_from_resource_name(input_data) self.assertEqual(None, actual) input_data = 666 actual = GCPUtils.get_entity_name_from_resource_name(input_data) self.assertEqual(None, actual)
def update_healthcheck(client, healthcheck, params, name, project_id, resource_type='HTTP'): """ Update a Healthcheck. If the healthcheck has not changed, the update will not occur. :param client: An initialized GCE Compute Discovery resource. :type client: :class: `googleapiclient.discovery.Resource` :param healthcheck: Name of the Url Map. :type healthcheck: ``dict`` :param params: Dictionary of arguments from AnsibleModule. :type params: ``dict`` :param name: Name of the Url Map. :type name: ``str`` :param project_id: The GCP project ID. :type project_id: ``str`` :return: Tuple with changed status and response dict :rtype: ``tuple`` in the format of (bool, dict) """ gcp_dict = _build_healthcheck_dict(params) ans = GCPUtils.are_params_equal(healthcheck, gcp_dict) if ans: return (False, 'no update necessary') try: resource, entity_name = _get_req_resource(client, resource_type) args = {'project': project_id, entity_name: name, 'body': gcp_dict} req = resource.update(**args) return_data = GCPUtils.execute_api_client_req(req, client=client, raw=False) return (True, return_data) except Exception: raise
def update_global_forwarding_rule(client, forwarding_rule, params, name, project_id): """ Update a Global Forwarding_Rule. Currently, only a target can be updated. If the forwarding_rule has not changed, the update will not occur. :param client: An initialized GCE Compute Discovery resource. :type client: :class: `googleapiclient.discovery.Resource` :param forwarding_rule: Name of the Target Proxy. :type forwarding_rule: ``dict`` :param params: Dictionary of arguments from AnsibleModule. :type params: ``dict`` :param name: Name of the Global Forwarding Rule. :type name: ``str`` :param project_id: The GCP project ID. :type project_id: ``str`` :return: Tuple with changed status and response dict :rtype: ``tuple`` in the format of (bool, dict) """ gcp_dict = _build_global_forwarding_rule_dict(params, project_id) GCPUtils.are_params_equal(forwarding_rule, gcp_dict) if forwarding_rule['target'] == gcp_dict['target']: return (False, 'no update necessary') try: req = client.globalForwardingRules().setTarget( project=project_id, forwardingRule=name, body={'target': gcp_dict['target']}) return_data = GCPUtils.execute_api_client_req(req, client=client, raw=False) return (True, return_data) except Exception: raise
def _build_target_proxy_dict(params, project_id=None): """ Reformat services in Ansible Params. :param params: Params from AnsibleModule object :type params: ``dict`` :param project_id: The GCP project ID. :type project_id: ``str`` :return: dictionary suitable for submission to GCP UrlMap API. :rtype ``dict`` """ url = '' if project_id: url = GCPUtils.build_googleapi_url(project_id) gcp_dict = GCPUtils.params_to_gcp_dict(params, 'target_proxy_name') if 'urlMap' in gcp_dict: gcp_dict['urlMap'] = '%s/global/urlMaps/%s' % (url, gcp_dict['urlMap']) return gcp_dict
def update_target_http_proxy(client, target_proxy, params, name, project_id): """ Update a HTTP Target_Proxy. Currently only the Url Map can be updated. If the target_proxy has not changed, the update will not occur. :param client: An initialized GCE Compute Discovery resource. :type client: :class: `googleapiclient.discovery.Resource` :param target_proxy: Name of the Target Proxy. :type target_proxy: ``dict`` :param params: Dictionary of arguments from AnsibleModule. :type params: ``dict`` :param name: Name of the Target Proxy. :type name: ``str`` :param project_id: The GCP project ID. :type project_id: ``str`` :return: Tuple with changed status and response dict :rtype: ``tuple`` in the format of (bool, dict) """ gcp_dict = _build_target_proxy_dict(params, project_id) GCPUtils.are_params_equal(target_proxy, gcp_dict) if target_proxy['urlMap'] == gcp_dict['urlMap']: return (False, 'no update necessary') try: req = client.targetHttpProxies().setUrlMap( project=project_id, targetHttpProxy=name, body={"urlMap": gcp_dict['urlMap']}) return_data = GCPUtils.execute_api_client_req(req, client=client, raw=False) return (True, return_data) except Exception: raise
def update_url_map(client, url_map, params, name, project_id): """ Update a Url_Map. If the url_map has not changed, the update will not occur. :param client: An initialized GCE Compute Discovery resource. :type client: :class: `googleapiclient.discovery.Resource` :param url_map: Name of the Url Map. :type url_map: ``dict`` :param params: Dictionary of arguments from AnsibleModule. :type params: ``dict`` :param name: Name of the Url Map. :type name: ``str`` :param project_id: The GCP project ID. :type project_id: ``str`` :return: Tuple with changed status and response dict :rtype: ``tuple`` in the format of (bool, dict) """ gcp_dict = _build_url_map_dict(params, project_id) ans = GCPUtils.are_params_equal(url_map, gcp_dict) if ans: return (False, 'no update necessary') gcp_dict['fingerprint'] = url_map['fingerprint'] try: req = client.urlMaps().update(project=project_id, urlMap=name, body=gcp_dict) return_data = GCPUtils.execute_api_client_req(req, client=client, raw=False) return (True, return_data) except Exception: raise
def get_target_http_proxy(client, name, project_id=None): """ Get a Target HTTP Proxy from GCP. :param client: An initialized GCE Compute Discovery resource. :type client: :class: `googleapiclient.discovery.Resource` :param name: Name of the Target Proxy. :type name: ``str`` :param project_id: The GCP project ID. :type project_id: ``str`` :return: A dict resp from the respective GCP 'get' request. :rtype: ``dict`` """ req = client.targetHttpProxies().get(project=project_id, targetHttpProxy=name) return GCPUtils.execute_api_client_req(req, raise_404=False)
def get_url_map(client, name, project_id=None): """ Get a Url_Map from GCP. :param client: An initialized GCE Compute Discovery resource. :type client: :class: `googleapiclient.discovery.Resource` :param name: Name of the Url Map. :type name: ``str`` :param project_id: The GCP project ID. :type project_id: ``str`` :return: A dict resp from the respective GCP 'get' request. :rtype: ``dict`` """ try: req = client.urlMaps().get(project=project_id, urlMap=name) return GCPUtils.execute_api_client_req(req, raise_404=False) except Exception: raise
def test_params_to_gcp_dict(self): expected = { 'description': 'foo_url_map description', 'hostRules': [{ 'description': 'host rules description', 'hosts': ['www.example.com', 'www2.example.com'], 'pathMatcher': 'host_rules_path_matcher' }], 'name': 'foo_url_map_name', 'pathMatchers': [{ 'defaultService': 'bes-pathmatcher-one-default', 'description': 'path matcher one', 'name': 'path_matcher_one', 'pathRules': [{ 'paths': ['/', '/aboutus'], 'service': 'my-one-bes' }] }, { 'defaultService': 'bes-pathmatcher-two-default', 'description': 'path matcher two', 'name': 'path_matcher_two', 'pathRules': [{ 'paths': ['/webapp', '/graphs'], 'service': 'my-two-bes' }] }] } actual = GCPUtils.params_to_gcp_dict(self.params_dict, 'url_map_name') self.assertEqual(expected, actual)
def delete_url_map(client, name, project_id): """ Delete a Url_Map. :param client: An initialized GCE Compute Discover resource. :type client: :class: `googleapiclient.discovery.Resource` :param name: Name of the Url Map. :type name: ``str`` :param project_id: The GCP project ID. :type project_id: ``str`` :return: Tuple with changed status and response dict :rtype: ``tuple`` in the format of (bool, dict) """ try: req = client.urlMaps().delete(project=project_id, urlMap=name) return_data = GCPUtils.execute_api_client_req(req, client) return (True, return_data) except Exception: raise
def delete_global_forwarding_rule(client, name, project_id): """ Delete a Global Forwarding Rule. :param client: An initialized GCE Compute Discovery resource. :type client: :class: `googleapiclient.discovery.Resource` :param name: Name of the Target Proxy. :type name: ``str`` :param project_id: The GCP project ID. :type project_id: ``str`` :return: Tuple with changed status and response dict :rtype: ``tuple`` in the format of (bool, dict) """ try: req = client.globalForwardingRules().delete(project=project_id, forwardingRule=name) return_data = GCPUtils.execute_api_client_req(req, client) return (True, return_data) except Exception: raise
def get_healthcheck(client, name, project_id=None, resource_type='HTTP'): """ Get a Healthcheck from GCP. :param client: An initialized GCE Compute Discovery resource. :type client: :class: `googleapiclient.discovery.Resource` :param name: Name of the Url Map. :type name: ``str`` :param project_id: The GCP project ID. :type project_id: ``str`` :return: A dict resp from the respective GCP 'get' request. :rtype: ``dict`` """ try: resource, entity_name = _get_req_resource(client, resource_type) args = {'project': project_id, entity_name: name} req = resource.get(**args) return GCPUtils.execute_api_client_req(req, raise_404=False) except Exception: raise
def delete_healthcheck(client, name, project_id, resource_type='HTTP'): """ Delete a Healthcheck. :param client: An initialized GCE Compute Discovery resource. :type client: :class: `googleapiclient.discovery.Resource` :param name: Name of the Url Map. :type name: ``str`` :param project_id: The GCP project ID. :type project_id: ``str`` :return: Tuple with changed status and response dict :rtype: ``tuple`` in the format of (bool, dict) """ try: resource, entity_name = _get_req_resource(client, resource_type) args = {'project': project_id, entity_name: name} req = resource.delete(**args) return_data = GCPUtils.execute_api_client_req(req, client) return (True, return_data) except Exception: raise
def test_are_params_equal(self): params1 = {'one': 1} params2 = {'one': 1} actual = GCPUtils.are_params_equal(params1, params2) self.assertTrue(actual) params1 = {'one': 1} params2 = {'two': 2} actual = GCPUtils.are_params_equal(params1, params2) self.assertFalse(actual) params1 = {'three': 3, 'two': 2, 'one': 1} params2 = {'one': 1, 'two': 2, 'three': 3} actual = GCPUtils.are_params_equal(params1, params2) self.assertTrue(actual) params1 = { "creationTimestamp": "2017-04-21T11:19:20.718-07:00", "defaultService": "https://www.googleapis.com/compute/v1/projects/myproject/global/backendServices/default-backend-service", "description": "", "fingerprint": "ickr_pwlZPU=", "hostRules": [{ "description": "", "hosts": ["*."], "pathMatcher": "path-matcher-one" }], "id": "8566395781175047111", "kind": "compute#urlMap", "name": "newtesturlmap-foo", "pathMatchers": [{ "defaultService": "https://www.googleapis.com/compute/v1/projects/myproject/global/backendServices/bes-pathmatcher-one-default", "description": "path matcher one", "name": "path-matcher-one", "pathRules": [{ "paths": ["/data", "/aboutus"], "service": "https://www.googleapis.com/compute/v1/projects/myproject/global/backendServices/my-one-bes" }] }], "selfLink": "https://www.googleapis.com/compute/v1/projects/myproject/global/urlMaps/newtesturlmap-foo" } params2 = { "defaultService": "https://www.googleapis.com/compute/v1/projects/myproject/global/backendServices/default-backend-service", "hostRules": [{ "description": "", "hosts": ["*."], "pathMatcher": "path-matcher-one" }], "name": "newtesturlmap-foo", "pathMatchers": [{ "defaultService": "https://www.googleapis.com/compute/v1/projects/myproject/global/backendServices/bes-pathmatcher-one-default", "description": "path matcher one", "name": "path-matcher-one", "pathRules": [{ "paths": ["/data", "/aboutus"], "service": "https://www.googleapis.com/compute/v1/projects/myproject/global/backendServices/my-one-bes" }] }], } # params1 has exclude fields, params2 doesn't. Should be equal actual = GCPUtils.are_params_equal(params1, params2) self.assertTrue(actual)
def test_parse_gcp_url(self): # region, resource, entity, method input_url = 'https://www.googleapis.com/compute/v1/projects/myproject/regions/us-east1/instanceGroupManagers/my-mig/recreateInstances' actual = GCPUtils.parse_gcp_url(input_url) self.assertEqual('compute', actual['service']) self.assertEqual('v1', actual['api_version']) self.assertEqual('myproject', actual['project']) self.assertEqual('us-east1', actual['region']) self.assertEqual('instanceGroupManagers', actual['resource_name']) self.assertEqual('my-mig', actual['entity_name']) self.assertEqual('recreateInstances', actual['method_name']) # zone, resource, entity, method input_url = 'https://www.googleapis.com/compute/v1/projects/myproject/zones/us-east1-c/instanceGroupManagers/my-mig/recreateInstances' actual = GCPUtils.parse_gcp_url(input_url) self.assertEqual('compute', actual['service']) self.assertEqual('v1', actual['api_version']) self.assertEqual('myproject', actual['project']) self.assertEqual('us-east1-c', actual['zone']) self.assertEqual('instanceGroupManagers', actual['resource_name']) self.assertEqual('my-mig', actual['entity_name']) self.assertEqual('recreateInstances', actual['method_name']) # global, resource input_url = 'https://www.googleapis.com/compute/v1/projects/myproject/global/urlMaps' actual = GCPUtils.parse_gcp_url(input_url) self.assertEqual('compute', actual['service']) self.assertEqual('v1', actual['api_version']) self.assertEqual('myproject', actual['project']) self.assertTrue('global' in actual) self.assertTrue(actual['global']) self.assertEqual('urlMaps', actual['resource_name']) # global, resource, entity input_url = 'https://www.googleapis.com/compute/v1/projects/myproject/global/urlMaps/my-url-map' actual = GCPUtils.parse_gcp_url(input_url) self.assertEqual('myproject', actual['project']) self.assertTrue('global' in actual) self.assertTrue(actual['global']) self.assertEqual('v1', actual['api_version']) self.assertEqual('compute', actual['service']) # global URL, resource, entity, method_name input_url = 'https://www.googleapis.com/compute/v1/projects/myproject/global/backendServices/mybackendservice/getHealth' actual = GCPUtils.parse_gcp_url(input_url) self.assertEqual('compute', actual['service']) self.assertEqual('v1', actual['api_version']) self.assertEqual('myproject', actual['project']) self.assertTrue('global' in actual) self.assertTrue(actual['global']) self.assertEqual('backendServices', actual['resource_name']) self.assertEqual('mybackendservice', actual['entity_name']) self.assertEqual('getHealth', actual['method_name']) # no location in URL input_url = 'https://www.googleapis.com/compute/v1/projects/myproject/targetHttpProxies/mytargetproxy/setUrlMap' actual = GCPUtils.parse_gcp_url(input_url) self.assertEqual('compute', actual['service']) self.assertEqual('v1', actual['api_version']) self.assertEqual('myproject', actual['project']) self.assertFalse('global' in actual) self.assertEqual('targetHttpProxies', actual['resource_name']) self.assertEqual('mytargetproxy', actual['entity_name']) self.assertEqual('setUrlMap', actual['method_name']) input_url = 'https://www.googleapis.com/compute/v1/projects/myproject/targetHttpProxies/mytargetproxy' actual = GCPUtils.parse_gcp_url(input_url) self.assertEqual('compute', actual['service']) self.assertEqual('v1', actual['api_version']) self.assertEqual('myproject', actual['project']) self.assertFalse('global' in actual) self.assertEqual('targetHttpProxies', actual['resource_name']) self.assertEqual('mytargetproxy', actual['entity_name']) input_url = 'https://www.googleapis.com/compute/v1/projects/myproject/targetHttpProxies' actual = GCPUtils.parse_gcp_url(input_url) self.assertEqual('compute', actual['service']) self.assertEqual('v1', actual['api_version']) self.assertEqual('myproject', actual['project']) self.assertFalse('global' in actual) self.assertEqual('targetHttpProxies', actual['resource_name']) # test exceptions no_projects_input_url = 'https://www.googleapis.com/compute/v1/not-projects/myproject/global/backendServices/mybackendservice/getHealth' no_resource_input_url = 'https://www.googleapis.com/compute/v1/not-projects/myproject/global' no_resource_no_loc_input_url = 'https://www.googleapis.com/compute/v1/not-projects/myproject' with self.assertRaises(GCPInvalidURLError) as cm: GCPUtils.parse_gcp_url(no_projects_input_url) self.assertTrue(cm.exception, GCPInvalidURLError) with self.assertRaises(GCPInvalidURLError) as cm: GCPUtils.parse_gcp_url(no_resource_input_url) self.assertTrue(cm.exception, GCPInvalidURLError) with self.assertRaises(GCPInvalidURLError) as cm: GCPUtils.parse_gcp_url(no_resource_no_loc_input_url) self.assertTrue(cm.exception, GCPInvalidURLError)