1#!/usr/bin/python 2# -*- coding: utf-8 -*- 3# 4# Copyright (C) 2017 Google 5# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6# ---------------------------------------------------------------------------- 7# 8# *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** 9# 10# ---------------------------------------------------------------------------- 11# 12# This file is automatically generated by Magic Modules and manual 13# changes will be clobbered when the file is regenerated. 14# 15# Please read more about how to change this file at 16# https://www.github.com/GoogleCloudPlatform/magic-modules 17# 18# ---------------------------------------------------------------------------- 19 20from __future__ import absolute_import, division, print_function 21 22__metaclass__ = type 23 24################################################################################ 25# Documentation 26################################################################################ 27 28ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ["preview"], 'supported_by': 'community'} 29 30DOCUMENTATION = ''' 31--- 32module: gcp_compute_health_check 33description: 34- Health Checks determine whether instances are responsive and able to do work. 35- They are an important part of a comprehensive load balancing configuration, as they 36 enable monitoring instances behind load balancers. 37- Health Checks poll instances at a specified interval. Instances that do not respond 38 successfully to some number of probes in a row are marked as unhealthy. No new connections 39 are sent to unhealthy instances, though existing connections will continue. The 40 health check will continue to poll unhealthy instances. If an instance later responds 41 successfully to some number of consecutive probes, it is marked healthy again and 42 can receive new connections. 43short_description: Creates a GCP HealthCheck 44version_added: 2.6 45author: Google Inc. (@googlecloudplatform) 46requirements: 47- python >= 2.6 48- requests >= 2.18.4 49- google-auth >= 1.3.0 50options: 51 state: 52 description: 53 - Whether the given object should exist in GCP 54 choices: 55 - present 56 - absent 57 default: present 58 type: str 59 check_interval_sec: 60 description: 61 - How often (in seconds) to send a health check. The default value is 5 seconds. 62 required: false 63 default: '5' 64 type: int 65 description: 66 description: 67 - An optional description of this resource. Provide this property when you create 68 the resource. 69 required: false 70 type: str 71 healthy_threshold: 72 description: 73 - A so-far unhealthy instance will be marked healthy after this many consecutive 74 successes. The default value is 2. 75 required: false 76 default: '2' 77 type: int 78 name: 79 description: 80 - Name of the resource. Provided by the client when the resource is created. The 81 name must be 1-63 characters long, and comply with RFC1035. Specifically, the 82 name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` 83 which means the first character must be a lowercase letter, and all following 84 characters must be a dash, lowercase letter, or digit, except the last character, 85 which cannot be a dash. 86 required: true 87 type: str 88 timeout_sec: 89 description: 90 - How long (in seconds) to wait before claiming failure. 91 - The default value is 5 seconds. It is invalid for timeoutSec to have greater 92 value than checkIntervalSec. 93 required: false 94 default: '5' 95 type: int 96 aliases: 97 - timeout_seconds 98 unhealthy_threshold: 99 description: 100 - A so-far healthy instance will be marked unhealthy after this many consecutive 101 failures. The default value is 2. 102 required: false 103 default: '2' 104 type: int 105 type: 106 description: 107 - Specifies the type of the healthCheck, either TCP, SSL, HTTP or HTTPS. If not 108 specified, the default is TCP. Exactly one of the protocol-specific health check 109 field must be specified, which must match type field. 110 - 'Some valid choices include: "TCP", "SSL", "HTTP", "HTTPS"' 111 required: false 112 type: str 113 http_health_check: 114 description: 115 - A nested object resource. 116 required: false 117 type: dict 118 suboptions: 119 host: 120 description: 121 - The value of the host header in the HTTP health check request. 122 - If left empty (default value), the public IP on behalf of which this health 123 check is performed will be used. 124 required: false 125 type: str 126 request_path: 127 description: 128 - The request path of the HTTP health check request. 129 - The default value is /. 130 required: false 131 default: "/" 132 type: str 133 response: 134 description: 135 - The bytes to match against the beginning of the response data. If left empty 136 (the default value), any response will indicate health. The response data 137 can only be ASCII. 138 required: false 139 type: str 140 port: 141 description: 142 - The TCP port number for the HTTP health check request. 143 - The default value is 80. 144 required: false 145 type: int 146 port_name: 147 description: 148 - Port name as defined in InstanceGroup#NamedPort#name. If both port and port_name 149 are defined, port takes precedence. 150 required: false 151 type: str 152 proxy_header: 153 description: 154 - Specifies the type of proxy header to append before sending data to the 155 backend, either NONE or PROXY_V1. The default is NONE. 156 - 'Some valid choices include: "NONE", "PROXY_V1"' 157 required: false 158 default: NONE 159 type: str 160 port_specification: 161 description: 162 - 'Specifies how port is selected for health checking, can be one of the following 163 values: * `USE_FIXED_PORT`: The port number in `port` is used for health 164 checking.' 165 - "* `USE_NAMED_PORT`: The `portName` is used for health checking." 166 - "* `USE_SERVING_PORT`: For NetworkEndpointGroup, the port specified for 167 each network endpoint is used for health checking. For other backends, the 168 port or named port specified in the Backend Service is used for health checking." 169 - If not specified, HTTP health check follows behavior specified in `port` 170 and `portName` fields. 171 - 'Some valid choices include: "USE_FIXED_PORT", "USE_NAMED_PORT", "USE_SERVING_PORT"' 172 required: false 173 type: str 174 version_added: 2.9 175 https_health_check: 176 description: 177 - A nested object resource. 178 required: false 179 type: dict 180 suboptions: 181 host: 182 description: 183 - The value of the host header in the HTTPS health check request. 184 - If left empty (default value), the public IP on behalf of which this health 185 check is performed will be used. 186 required: false 187 type: str 188 request_path: 189 description: 190 - The request path of the HTTPS health check request. 191 - The default value is /. 192 required: false 193 default: "/" 194 type: str 195 response: 196 description: 197 - The bytes to match against the beginning of the response data. If left empty 198 (the default value), any response will indicate health. The response data 199 can only be ASCII. 200 required: false 201 type: str 202 port: 203 description: 204 - The TCP port number for the HTTPS health check request. 205 - The default value is 443. 206 required: false 207 type: int 208 port_name: 209 description: 210 - Port name as defined in InstanceGroup#NamedPort#name. If both port and port_name 211 are defined, port takes precedence. 212 required: false 213 type: str 214 proxy_header: 215 description: 216 - Specifies the type of proxy header to append before sending data to the 217 backend, either NONE or PROXY_V1. The default is NONE. 218 - 'Some valid choices include: "NONE", "PROXY_V1"' 219 required: false 220 default: NONE 221 type: str 222 port_specification: 223 description: 224 - 'Specifies how port is selected for health checking, can be one of the following 225 values: * `USE_FIXED_PORT`: The port number in `port` is used for health 226 checking.' 227 - "* `USE_NAMED_PORT`: The `portName` is used for health checking." 228 - "* `USE_SERVING_PORT`: For NetworkEndpointGroup, the port specified for 229 each network endpoint is used for health checking. For other backends, the 230 port or named port specified in the Backend Service is used for health checking." 231 - If not specified, HTTPS health check follows behavior specified in `port` 232 and `portName` fields. 233 - 'Some valid choices include: "USE_FIXED_PORT", "USE_NAMED_PORT", "USE_SERVING_PORT"' 234 required: false 235 type: str 236 version_added: 2.9 237 tcp_health_check: 238 description: 239 - A nested object resource. 240 required: false 241 type: dict 242 suboptions: 243 request: 244 description: 245 - The application data to send once the TCP connection has been established 246 (default value is empty). If both request and response are empty, the connection 247 establishment alone will indicate health. The request data can only be ASCII. 248 required: false 249 type: str 250 response: 251 description: 252 - The bytes to match against the beginning of the response data. If left empty 253 (the default value), any response will indicate health. The response data 254 can only be ASCII. 255 required: false 256 type: str 257 port: 258 description: 259 - The TCP port number for the TCP health check request. 260 - The default value is 443. 261 required: false 262 type: int 263 port_name: 264 description: 265 - Port name as defined in InstanceGroup#NamedPort#name. If both port and port_name 266 are defined, port takes precedence. 267 required: false 268 type: str 269 proxy_header: 270 description: 271 - Specifies the type of proxy header to append before sending data to the 272 backend, either NONE or PROXY_V1. The default is NONE. 273 - 'Some valid choices include: "NONE", "PROXY_V1"' 274 required: false 275 default: NONE 276 type: str 277 port_specification: 278 description: 279 - 'Specifies how port is selected for health checking, can be one of the following 280 values: * `USE_FIXED_PORT`: The port number in `port` is used for health 281 checking.' 282 - "* `USE_NAMED_PORT`: The `portName` is used for health checking." 283 - "* `USE_SERVING_PORT`: For NetworkEndpointGroup, the port specified for 284 each network endpoint is used for health checking. For other backends, the 285 port or named port specified in the Backend Service is used for health checking." 286 - If not specified, TCP health check follows behavior specified in `port` 287 and `portName` fields. 288 - 'Some valid choices include: "USE_FIXED_PORT", "USE_NAMED_PORT", "USE_SERVING_PORT"' 289 required: false 290 type: str 291 version_added: 2.9 292 ssl_health_check: 293 description: 294 - A nested object resource. 295 required: false 296 type: dict 297 suboptions: 298 request: 299 description: 300 - The application data to send once the SSL connection has been established 301 (default value is empty). If both request and response are empty, the connection 302 establishment alone will indicate health. The request data can only be ASCII. 303 required: false 304 type: str 305 response: 306 description: 307 - The bytes to match against the beginning of the response data. If left empty 308 (the default value), any response will indicate health. The response data 309 can only be ASCII. 310 required: false 311 type: str 312 port: 313 description: 314 - The TCP port number for the SSL health check request. 315 - The default value is 443. 316 required: false 317 type: int 318 port_name: 319 description: 320 - Port name as defined in InstanceGroup#NamedPort#name. If both port and port_name 321 are defined, port takes precedence. 322 required: false 323 type: str 324 proxy_header: 325 description: 326 - Specifies the type of proxy header to append before sending data to the 327 backend, either NONE or PROXY_V1. The default is NONE. 328 - 'Some valid choices include: "NONE", "PROXY_V1"' 329 required: false 330 default: NONE 331 type: str 332 port_specification: 333 description: 334 - 'Specifies how port is selected for health checking, can be one of the following 335 values: * `USE_FIXED_PORT`: The port number in `port` is used for health 336 checking.' 337 - "* `USE_NAMED_PORT`: The `portName` is used for health checking." 338 - "* `USE_SERVING_PORT`: For NetworkEndpointGroup, the port specified for 339 each network endpoint is used for health checking. For other backends, the 340 port or named port specified in the Backend Service is used for health checking." 341 - If not specified, SSL health check follows behavior specified in `port` 342 and `portName` fields. 343 - 'Some valid choices include: "USE_FIXED_PORT", "USE_NAMED_PORT", "USE_SERVING_PORT"' 344 required: false 345 type: str 346 version_added: 2.9 347extends_documentation_fragment: gcp 348notes: 349- 'API Reference: U(https://cloud.google.com/compute/docs/reference/rest/v1/healthChecks)' 350- 'Official Documentation: U(https://cloud.google.com/load-balancing/docs/health-checks)' 351''' 352 353EXAMPLES = ''' 354- name: create a health check 355 gcp_compute_health_check: 356 name: test_object 357 type: TCP 358 tcp_health_check: 359 port_name: service-health 360 request: ping 361 response: pong 362 healthy_threshold: 10 363 timeout_sec: 2 364 unhealthy_threshold: 5 365 project: test_project 366 auth_kind: serviceaccount 367 service_account_file: "/tmp/auth.pem" 368 state: present 369''' 370 371RETURN = ''' 372checkIntervalSec: 373 description: 374 - How often (in seconds) to send a health check. The default value is 5 seconds. 375 returned: success 376 type: int 377creationTimestamp: 378 description: 379 - Creation timestamp in RFC3339 text format. 380 returned: success 381 type: str 382description: 383 description: 384 - An optional description of this resource. Provide this property when you create 385 the resource. 386 returned: success 387 type: str 388healthyThreshold: 389 description: 390 - A so-far unhealthy instance will be marked healthy after this many consecutive 391 successes. The default value is 2. 392 returned: success 393 type: int 394id: 395 description: 396 - The unique identifier for the resource. This identifier is defined by the server. 397 returned: success 398 type: int 399name: 400 description: 401 - Name of the resource. Provided by the client when the resource is created. The 402 name must be 1-63 characters long, and comply with RFC1035. Specifically, the 403 name must be 1-63 characters long and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` 404 which means the first character must be a lowercase letter, and all following 405 characters must be a dash, lowercase letter, or digit, except the last character, 406 which cannot be a dash. 407 returned: success 408 type: str 409timeoutSec: 410 description: 411 - How long (in seconds) to wait before claiming failure. 412 - The default value is 5 seconds. It is invalid for timeoutSec to have greater value 413 than checkIntervalSec. 414 returned: success 415 type: int 416unhealthyThreshold: 417 description: 418 - A so-far healthy instance will be marked unhealthy after this many consecutive 419 failures. The default value is 2. 420 returned: success 421 type: int 422type: 423 description: 424 - Specifies the type of the healthCheck, either TCP, SSL, HTTP or HTTPS. If not 425 specified, the default is TCP. Exactly one of the protocol-specific health check 426 field must be specified, which must match type field. 427 returned: success 428 type: str 429httpHealthCheck: 430 description: 431 - A nested object resource. 432 returned: success 433 type: complex 434 contains: 435 host: 436 description: 437 - The value of the host header in the HTTP health check request. 438 - If left empty (default value), the public IP on behalf of which this health 439 check is performed will be used. 440 returned: success 441 type: str 442 requestPath: 443 description: 444 - The request path of the HTTP health check request. 445 - The default value is /. 446 returned: success 447 type: str 448 response: 449 description: 450 - The bytes to match against the beginning of the response data. If left empty 451 (the default value), any response will indicate health. The response data 452 can only be ASCII. 453 returned: success 454 type: str 455 port: 456 description: 457 - The TCP port number for the HTTP health check request. 458 - The default value is 80. 459 returned: success 460 type: int 461 portName: 462 description: 463 - Port name as defined in InstanceGroup#NamedPort#name. If both port and port_name 464 are defined, port takes precedence. 465 returned: success 466 type: str 467 proxyHeader: 468 description: 469 - Specifies the type of proxy header to append before sending data to the backend, 470 either NONE or PROXY_V1. The default is NONE. 471 returned: success 472 type: str 473 portSpecification: 474 description: 475 - 'Specifies how port is selected for health checking, can be one of the following 476 values: * `USE_FIXED_PORT`: The port number in `port` is used for health checking.' 477 - "* `USE_NAMED_PORT`: The `portName` is used for health checking." 478 - "* `USE_SERVING_PORT`: For NetworkEndpointGroup, the port specified for each 479 network endpoint is used for health checking. For other backends, the port 480 or named port specified in the Backend Service is used for health checking." 481 - If not specified, HTTP health check follows behavior specified in `port` and 482 `portName` fields. 483 returned: success 484 type: str 485httpsHealthCheck: 486 description: 487 - A nested object resource. 488 returned: success 489 type: complex 490 contains: 491 host: 492 description: 493 - The value of the host header in the HTTPS health check request. 494 - If left empty (default value), the public IP on behalf of which this health 495 check is performed will be used. 496 returned: success 497 type: str 498 requestPath: 499 description: 500 - The request path of the HTTPS health check request. 501 - The default value is /. 502 returned: success 503 type: str 504 response: 505 description: 506 - The bytes to match against the beginning of the response data. If left empty 507 (the default value), any response will indicate health. The response data 508 can only be ASCII. 509 returned: success 510 type: str 511 port: 512 description: 513 - The TCP port number for the HTTPS health check request. 514 - The default value is 443. 515 returned: success 516 type: int 517 portName: 518 description: 519 - Port name as defined in InstanceGroup#NamedPort#name. If both port and port_name 520 are defined, port takes precedence. 521 returned: success 522 type: str 523 proxyHeader: 524 description: 525 - Specifies the type of proxy header to append before sending data to the backend, 526 either NONE or PROXY_V1. The default is NONE. 527 returned: success 528 type: str 529 portSpecification: 530 description: 531 - 'Specifies how port is selected for health checking, can be one of the following 532 values: * `USE_FIXED_PORT`: The port number in `port` is used for health checking.' 533 - "* `USE_NAMED_PORT`: The `portName` is used for health checking." 534 - "* `USE_SERVING_PORT`: For NetworkEndpointGroup, the port specified for each 535 network endpoint is used for health checking. For other backends, the port 536 or named port specified in the Backend Service is used for health checking." 537 - If not specified, HTTPS health check follows behavior specified in `port` 538 and `portName` fields. 539 returned: success 540 type: str 541tcpHealthCheck: 542 description: 543 - A nested object resource. 544 returned: success 545 type: complex 546 contains: 547 request: 548 description: 549 - The application data to send once the TCP connection has been established 550 (default value is empty). If both request and response are empty, the connection 551 establishment alone will indicate health. The request data can only be ASCII. 552 returned: success 553 type: str 554 response: 555 description: 556 - The bytes to match against the beginning of the response data. If left empty 557 (the default value), any response will indicate health. The response data 558 can only be ASCII. 559 returned: success 560 type: str 561 port: 562 description: 563 - The TCP port number for the TCP health check request. 564 - The default value is 443. 565 returned: success 566 type: int 567 portName: 568 description: 569 - Port name as defined in InstanceGroup#NamedPort#name. If both port and port_name 570 are defined, port takes precedence. 571 returned: success 572 type: str 573 proxyHeader: 574 description: 575 - Specifies the type of proxy header to append before sending data to the backend, 576 either NONE or PROXY_V1. The default is NONE. 577 returned: success 578 type: str 579 portSpecification: 580 description: 581 - 'Specifies how port is selected for health checking, can be one of the following 582 values: * `USE_FIXED_PORT`: The port number in `port` is used for health checking.' 583 - "* `USE_NAMED_PORT`: The `portName` is used for health checking." 584 - "* `USE_SERVING_PORT`: For NetworkEndpointGroup, the port specified for each 585 network endpoint is used for health checking. For other backends, the port 586 or named port specified in the Backend Service is used for health checking." 587 - If not specified, TCP health check follows behavior specified in `port` and 588 `portName` fields. 589 returned: success 590 type: str 591sslHealthCheck: 592 description: 593 - A nested object resource. 594 returned: success 595 type: complex 596 contains: 597 request: 598 description: 599 - The application data to send once the SSL connection has been established 600 (default value is empty). If both request and response are empty, the connection 601 establishment alone will indicate health. The request data can only be ASCII. 602 returned: success 603 type: str 604 response: 605 description: 606 - The bytes to match against the beginning of the response data. If left empty 607 (the default value), any response will indicate health. The response data 608 can only be ASCII. 609 returned: success 610 type: str 611 port: 612 description: 613 - The TCP port number for the SSL health check request. 614 - The default value is 443. 615 returned: success 616 type: int 617 portName: 618 description: 619 - Port name as defined in InstanceGroup#NamedPort#name. If both port and port_name 620 are defined, port takes precedence. 621 returned: success 622 type: str 623 proxyHeader: 624 description: 625 - Specifies the type of proxy header to append before sending data to the backend, 626 either NONE or PROXY_V1. The default is NONE. 627 returned: success 628 type: str 629 portSpecification: 630 description: 631 - 'Specifies how port is selected for health checking, can be one of the following 632 values: * `USE_FIXED_PORT`: The port number in `port` is used for health checking.' 633 - "* `USE_NAMED_PORT`: The `portName` is used for health checking." 634 - "* `USE_SERVING_PORT`: For NetworkEndpointGroup, the port specified for each 635 network endpoint is used for health checking. For other backends, the port 636 or named port specified in the Backend Service is used for health checking." 637 - If not specified, SSL health check follows behavior specified in `port` and 638 `portName` fields. 639 returned: success 640 type: str 641''' 642 643################################################################################ 644# Imports 645################################################################################ 646 647from ansible.module_utils.gcp_utils import navigate_hash, GcpSession, GcpModule, GcpRequest, remove_nones_from_dict, replace_resource_dict 648import json 649import time 650 651################################################################################ 652# Main 653################################################################################ 654 655 656def main(): 657 """Main function""" 658 659 module = GcpModule( 660 argument_spec=dict( 661 state=dict(default='present', choices=['present', 'absent'], type='str'), 662 check_interval_sec=dict(default=5, type='int'), 663 description=dict(type='str'), 664 healthy_threshold=dict(default=2, type='int'), 665 name=dict(required=True, type='str'), 666 timeout_sec=dict(default=5, type='int', aliases=['timeout_seconds']), 667 unhealthy_threshold=dict(default=2, type='int'), 668 type=dict(type='str'), 669 http_health_check=dict( 670 type='dict', 671 options=dict( 672 host=dict(type='str'), 673 request_path=dict(default='/', type='str'), 674 response=dict(type='str'), 675 port=dict(type='int'), 676 port_name=dict(type='str'), 677 proxy_header=dict(default='NONE', type='str'), 678 port_specification=dict(type='str'), 679 ), 680 ), 681 https_health_check=dict( 682 type='dict', 683 options=dict( 684 host=dict(type='str'), 685 request_path=dict(default='/', type='str'), 686 response=dict(type='str'), 687 port=dict(type='int'), 688 port_name=dict(type='str'), 689 proxy_header=dict(default='NONE', type='str'), 690 port_specification=dict(type='str'), 691 ), 692 ), 693 tcp_health_check=dict( 694 type='dict', 695 options=dict( 696 request=dict(type='str'), 697 response=dict(type='str'), 698 port=dict(type='int'), 699 port_name=dict(type='str'), 700 proxy_header=dict(default='NONE', type='str'), 701 port_specification=dict(type='str'), 702 ), 703 ), 704 ssl_health_check=dict( 705 type='dict', 706 options=dict( 707 request=dict(type='str'), 708 response=dict(type='str'), 709 port=dict(type='int'), 710 port_name=dict(type='str'), 711 proxy_header=dict(default='NONE', type='str'), 712 port_specification=dict(type='str'), 713 ), 714 ), 715 ), 716 mutually_exclusive=[['http_health_check', 'https_health_check', 'ssl_health_check', 'tcp_health_check']], 717 ) 718 719 if not module.params['scopes']: 720 module.params['scopes'] = ['https://www.googleapis.com/auth/compute'] 721 722 state = module.params['state'] 723 kind = 'compute#healthCheck' 724 725 fetch = fetch_resource(module, self_link(module), kind) 726 changed = False 727 728 if fetch: 729 if state == 'present': 730 if is_different(module, fetch): 731 update(module, self_link(module), kind) 732 fetch = fetch_resource(module, self_link(module), kind) 733 changed = True 734 else: 735 delete(module, self_link(module), kind) 736 fetch = {} 737 changed = True 738 else: 739 if state == 'present': 740 fetch = create(module, collection(module), kind) 741 changed = True 742 else: 743 fetch = {} 744 745 fetch.update({'changed': changed}) 746 747 module.exit_json(**fetch) 748 749 750def create(module, link, kind): 751 auth = GcpSession(module, 'compute') 752 return wait_for_operation(module, auth.post(link, resource_to_request(module))) 753 754 755def update(module, link, kind): 756 auth = GcpSession(module, 'compute') 757 return wait_for_operation(module, auth.put(link, resource_to_request(module))) 758 759 760def delete(module, link, kind): 761 auth = GcpSession(module, 'compute') 762 return wait_for_operation(module, auth.delete(link)) 763 764 765def resource_to_request(module): 766 request = { 767 u'kind': 'compute#healthCheck', 768 u'checkIntervalSec': module.params.get('check_interval_sec'), 769 u'description': module.params.get('description'), 770 u'healthyThreshold': module.params.get('healthy_threshold'), 771 u'name': module.params.get('name'), 772 u'timeoutSec': module.params.get('timeout_sec'), 773 u'unhealthyThreshold': module.params.get('unhealthy_threshold'), 774 u'type': module.params.get('type'), 775 u'httpHealthCheck': HealthCheckHttphealthcheck(module.params.get('http_health_check', {}), module).to_request(), 776 u'httpsHealthCheck': HealthCheckHttpshealthcheck(module.params.get('https_health_check', {}), module).to_request(), 777 u'tcpHealthCheck': HealthCheckTcphealthcheck(module.params.get('tcp_health_check', {}), module).to_request(), 778 u'sslHealthCheck': HealthCheckSslhealthcheck(module.params.get('ssl_health_check', {}), module).to_request(), 779 } 780 return_vals = {} 781 for k, v in request.items(): 782 if v or v is False: 783 return_vals[k] = v 784 785 return return_vals 786 787 788def fetch_resource(module, link, kind, allow_not_found=True): 789 auth = GcpSession(module, 'compute') 790 return return_if_object(module, auth.get(link), kind, allow_not_found) 791 792 793def self_link(module): 794 return "https://www.googleapis.com/compute/v1/projects/{project}/global/healthChecks/{name}".format(**module.params) 795 796 797def collection(module): 798 return "https://www.googleapis.com/compute/v1/projects/{project}/global/healthChecks".format(**module.params) 799 800 801def return_if_object(module, response, kind, allow_not_found=False): 802 # If not found, return nothing. 803 if allow_not_found and response.status_code == 404: 804 return None 805 806 # If no content, return nothing. 807 if response.status_code == 204: 808 return None 809 810 try: 811 module.raise_for_status(response) 812 result = response.json() 813 except getattr(json.decoder, 'JSONDecodeError', ValueError): 814 module.fail_json(msg="Invalid JSON response with error: %s" % response.text) 815 816 if navigate_hash(result, ['error', 'errors']): 817 module.fail_json(msg=navigate_hash(result, ['error', 'errors'])) 818 819 return result 820 821 822def is_different(module, response): 823 request = resource_to_request(module) 824 response = response_to_hash(module, response) 825 826 # Remove all output-only from response. 827 response_vals = {} 828 for k, v in response.items(): 829 if k in request: 830 response_vals[k] = v 831 832 request_vals = {} 833 for k, v in request.items(): 834 if k in response: 835 request_vals[k] = v 836 837 return GcpRequest(request_vals) != GcpRequest(response_vals) 838 839 840# Remove unnecessary properties from the response. 841# This is for doing comparisons with Ansible's current parameters. 842def response_to_hash(module, response): 843 return { 844 u'checkIntervalSec': response.get(u'checkIntervalSec'), 845 u'creationTimestamp': response.get(u'creationTimestamp'), 846 u'description': response.get(u'description'), 847 u'healthyThreshold': response.get(u'healthyThreshold'), 848 u'id': response.get(u'id'), 849 u'name': module.params.get('name'), 850 u'timeoutSec': response.get(u'timeoutSec'), 851 u'unhealthyThreshold': response.get(u'unhealthyThreshold'), 852 u'type': response.get(u'type'), 853 u'httpHealthCheck': HealthCheckHttphealthcheck(response.get(u'httpHealthCheck', {}), module).from_response(), 854 u'httpsHealthCheck': HealthCheckHttpshealthcheck(response.get(u'httpsHealthCheck', {}), module).from_response(), 855 u'tcpHealthCheck': HealthCheckTcphealthcheck(response.get(u'tcpHealthCheck', {}), module).from_response(), 856 u'sslHealthCheck': HealthCheckSslhealthcheck(response.get(u'sslHealthCheck', {}), module).from_response(), 857 } 858 859 860def async_op_url(module, extra_data=None): 861 if extra_data is None: 862 extra_data = {} 863 url = "https://www.googleapis.com/compute/v1/projects/{project}/global/operations/{op_id}" 864 combined = extra_data.copy() 865 combined.update(module.params) 866 return url.format(**combined) 867 868 869def wait_for_operation(module, response): 870 op_result = return_if_object(module, response, 'compute#operation') 871 if op_result is None: 872 return {} 873 status = navigate_hash(op_result, ['status']) 874 wait_done = wait_for_completion(status, op_result, module) 875 return fetch_resource(module, navigate_hash(wait_done, ['targetLink']), 'compute#healthCheck') 876 877 878def wait_for_completion(status, op_result, module): 879 op_id = navigate_hash(op_result, ['name']) 880 op_uri = async_op_url(module, {'op_id': op_id}) 881 while status != 'DONE': 882 raise_if_errors(op_result, ['error', 'errors'], module) 883 time.sleep(1.0) 884 op_result = fetch_resource(module, op_uri, 'compute#operation', False) 885 status = navigate_hash(op_result, ['status']) 886 return op_result 887 888 889def raise_if_errors(response, err_path, module): 890 errors = navigate_hash(response, err_path) 891 if errors is not None: 892 module.fail_json(msg=errors) 893 894 895class HealthCheckHttphealthcheck(object): 896 def __init__(self, request, module): 897 self.module = module 898 if request: 899 self.request = request 900 else: 901 self.request = {} 902 903 def to_request(self): 904 return remove_nones_from_dict( 905 { 906 u'host': self.request.get('host'), 907 u'requestPath': self.request.get('request_path'), 908 u'response': self.request.get('response'), 909 u'port': self.request.get('port'), 910 u'portName': self.request.get('port_name'), 911 u'proxyHeader': self.request.get('proxy_header'), 912 u'portSpecification': self.request.get('port_specification'), 913 } 914 ) 915 916 def from_response(self): 917 return remove_nones_from_dict( 918 { 919 u'host': self.request.get(u'host'), 920 u'requestPath': self.request.get(u'requestPath'), 921 u'response': self.request.get(u'response'), 922 u'port': self.request.get(u'port'), 923 u'portName': self.request.get(u'portName'), 924 u'proxyHeader': self.request.get(u'proxyHeader'), 925 u'portSpecification': self.request.get(u'portSpecification'), 926 } 927 ) 928 929 930class HealthCheckHttpshealthcheck(object): 931 def __init__(self, request, module): 932 self.module = module 933 if request: 934 self.request = request 935 else: 936 self.request = {} 937 938 def to_request(self): 939 return remove_nones_from_dict( 940 { 941 u'host': self.request.get('host'), 942 u'requestPath': self.request.get('request_path'), 943 u'response': self.request.get('response'), 944 u'port': self.request.get('port'), 945 u'portName': self.request.get('port_name'), 946 u'proxyHeader': self.request.get('proxy_header'), 947 u'portSpecification': self.request.get('port_specification'), 948 } 949 ) 950 951 def from_response(self): 952 return remove_nones_from_dict( 953 { 954 u'host': self.request.get(u'host'), 955 u'requestPath': self.request.get(u'requestPath'), 956 u'response': self.request.get(u'response'), 957 u'port': self.request.get(u'port'), 958 u'portName': self.request.get(u'portName'), 959 u'proxyHeader': self.request.get(u'proxyHeader'), 960 u'portSpecification': self.request.get(u'portSpecification'), 961 } 962 ) 963 964 965class HealthCheckTcphealthcheck(object): 966 def __init__(self, request, module): 967 self.module = module 968 if request: 969 self.request = request 970 else: 971 self.request = {} 972 973 def to_request(self): 974 return remove_nones_from_dict( 975 { 976 u'request': self.request.get('request'), 977 u'response': self.request.get('response'), 978 u'port': self.request.get('port'), 979 u'portName': self.request.get('port_name'), 980 u'proxyHeader': self.request.get('proxy_header'), 981 u'portSpecification': self.request.get('port_specification'), 982 } 983 ) 984 985 def from_response(self): 986 return remove_nones_from_dict( 987 { 988 u'request': self.request.get(u'request'), 989 u'response': self.request.get(u'response'), 990 u'port': self.request.get(u'port'), 991 u'portName': self.request.get(u'portName'), 992 u'proxyHeader': self.request.get(u'proxyHeader'), 993 u'portSpecification': self.request.get(u'portSpecification'), 994 } 995 ) 996 997 998class HealthCheckSslhealthcheck(object): 999 def __init__(self, request, module): 1000 self.module = module 1001 if request: 1002 self.request = request 1003 else: 1004 self.request = {} 1005 1006 def to_request(self): 1007 return remove_nones_from_dict( 1008 { 1009 u'request': self.request.get('request'), 1010 u'response': self.request.get('response'), 1011 u'port': self.request.get('port'), 1012 u'portName': self.request.get('port_name'), 1013 u'proxyHeader': self.request.get('proxy_header'), 1014 u'portSpecification': self.request.get('port_specification'), 1015 } 1016 ) 1017 1018 def from_response(self): 1019 return remove_nones_from_dict( 1020 { 1021 u'request': self.request.get(u'request'), 1022 u'response': self.request.get(u'response'), 1023 u'port': self.request.get(u'port'), 1024 u'portName': self.request.get(u'portName'), 1025 u'proxyHeader': self.request.get(u'proxyHeader'), 1026 u'portSpecification': self.request.get(u'portSpecification'), 1027 } 1028 ) 1029 1030 1031if __name__ == '__main__': 1032 main() 1033