Ryan Brown 6 years ago committed by GitHub
parent 3b5471a734
commit 18a088c64e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -81,11 +81,24 @@ options:
letter, and all following characters must be a dash, lowercase letter, or digit,
except the last character, which cannot be a dash.
required: true
network_tier:
description:
- 'The networking tier used for configuring this address. This field can take the
following values: PREMIUM or STANDARD. If this field is not specified, it is assumed
to be PREMIUM.'
required: false
version_added: 2.8
choices: ['PREMIUM', 'STANDARD']
subnetwork:
description:
- The URL of the subnetwork in which to reserve the address. If an IP address is specified,
it must be within the subnetwork's IP range.
- This field can only be used with INTERNAL type with GCE_ENDPOINT/DNS_RESOLVER purposes.
- 'This field represents a link to a Subnetwork resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_subnetwork
task and then set this subnetwork field to "{{ name-of-resource }}" Alternatively,
you can set this subnetwork to a dictionary with the selfLink key where the value
is the selfLink of your Subnetwork.'
required: false
version_added: 2.7
region:
@ -106,7 +119,7 @@ EXAMPLES = '''
name: test-address1
region: us-west1
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
@ -119,13 +132,13 @@ RETURN = '''
be inside the specified subnetwork, if any.
returned: success
type: str
address_type:
addressType:
description:
- The type of address to reserve, either INTERNAL or EXTERNAL.
- If unspecified, defaults to EXTERNAL.
returned: success
type: str
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -149,6 +162,13 @@ RETURN = '''
except the last character, which cannot be a dash.
returned: success
type: str
networkTier:
description:
- 'The networking tier used for configuring this address. This field can take the
following values: PREMIUM or STANDARD. If this field is not specified, it is assumed
to be PREMIUM.'
returned: success
type: str
subnetwork:
description:
- The URL of the subnetwork in which to reserve the address. If an IP address is specified,
@ -192,6 +212,7 @@ def main():
address_type=dict(default='EXTERNAL', type='str', choices=['INTERNAL', 'EXTERNAL']),
description=dict(type='str'),
name=dict(required=True, type='str'),
network_tier=dict(type='str', choices=['PREMIUM', 'STANDARD']),
subnetwork=dict(type='dict'),
region=dict(required=True, type='str')
)
@ -209,7 +230,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -233,8 +255,7 @@ def create(module, link, kind):
def update(module, link, kind):
auth = GcpSession(module, 'compute')
return wait_for_operation(module, auth.put(link, resource_to_request(module)))
module.fail_json(msg="Address cannot be edited")
def delete(module, link, kind):
@ -249,6 +270,7 @@ def resource_to_request(module):
u'addressType': module.params.get('address_type'),
u'description': module.params.get('description'),
u'name': module.params.get('name'),
u'networkTier': module.params.get('network_tier'),
u'subnetwork': replace_resource_dict(module.params.get(u'subnetwork', {}), 'selfLink')
}
return_vals = {}
@ -259,9 +281,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -272,9 +294,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/regions/{region}/addresses".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -289,8 +311,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result
@ -323,6 +343,7 @@ def response_to_hash(module, response):
u'description': response.get(u'description'),
u'id': response.get(u'id'),
u'name': response.get(u'name'),
u'networkTier': response.get(u'networkTier'),
u'subnetwork': response.get(u'subnetwork'),
u'users': response.get(u'users')
}

@ -62,7 +62,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -79,13 +79,13 @@ items:
be inside the specified subnetwork, if any.
returned: success
type: str
address_type:
addressType:
description:
- The type of address to reserve, either INTERNAL or EXTERNAL.
- If unspecified, defaults to EXTERNAL.
returned: success
type: str
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -109,6 +109,13 @@ items:
except the last character, which cannot be a dash.
returned: success
type: str
networkTier:
description:
- 'The networking tier used for configuring this address. This field can take the
following values: PREMIUM or STANDARD. If this field is not specified, it is assumed
to be PREMIUM.'
returned: success
type: str
subnetwork:
description:
- The URL of the subnetwork in which to reserve the address. If an IP address is specified,

@ -96,18 +96,18 @@ EXAMPLES = '''
description: A BackendBucket to connect LNB w/ Storage Bucket
enable_cdn: true
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
bucket_name:
bucketName:
description:
- Cloud Storage bucket name.
returned: success
type: str
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -118,7 +118,7 @@ RETURN = '''
resource is created.
returned: success
type: str
enable_cdn:
enableCdn:
description:
- If true, enable Cloud CDN for this BackendBucket.
returned: success
@ -178,7 +178,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -227,9 +228,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -240,9 +241,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/global/backendBuckets".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -257,8 +258,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result

@ -56,7 +56,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -66,12 +66,12 @@ items:
returned: always
type: complex
contains:
bucket_name:
bucketName:
description:
- Cloud Storage bucket name.
returned: success
type: str
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -82,7 +82,7 @@ items:
resource is created.
returned: success
type: str
enable_cdn:
enableCdn:
description:
- If true, enable Cloud CDN for this BackendBucket.
returned: success
@ -118,7 +118,7 @@ import json
def main():
module = GcpModule(
argument_spec=dict(
filters=dict(type='list', elements='str'),
filters=dict(type='list', elements='str')
)
)

@ -89,6 +89,11 @@ options:
- No two backends in a backend service are allowed to use same Instance Group resource.
- When the BackendService has load balancing scheme INTERNAL, the instance group must
be in a zone within the same region as the BackendService.
- 'This field represents a link to a InstanceGroup resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_instance_group
task and then set this group field to "{{ name-of-resource }}" Alternatively, you
can set this group to a dictionary with the selfLink key where the value is the
selfLink of your InstanceGroup.'
required: false
max_connections:
description:
@ -305,13 +310,13 @@ EXAMPLES = '''
- "{{ healthcheck.selfLink }}"
enable_cdn: true
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
affinity_cookie_ttl_sec:
affinityCookieTtlSec:
description:
- Lifetime of cookies in seconds if session_affinity is GENERATED_COOKIE. If set to
0, the cookie is non-persistent and lasts only until the end of the browser session
@ -325,7 +330,7 @@ RETURN = '''
returned: success
type: complex
contains:
balancing_mode:
balancingMode:
description:
- Specifies the balancing mode for this backend.
- For global HTTP(S) or TCP/SSL load balancing, the default is UTILIZATION. Valid
@ -333,7 +338,7 @@ RETURN = '''
- This cannot be used for internal load balancing.
returned: success
type: str
capacity_scaler:
capacityScaler:
description:
- A multiplier applied to the group's maximum servicing capacity (based on UTILIZATION,
RATE or CONNECTION).
@ -359,7 +364,7 @@ RETURN = '''
be in a zone within the same region as the BackendService.
returned: success
type: dict
max_connections:
maxConnections:
description:
- The max number of simultaneous connections for the group. Can be used with either
CONNECTION or UTILIZATION balancing modes.
@ -368,7 +373,7 @@ RETURN = '''
- This cannot be used for internal load balancing.
returned: success
type: int
max_connections_per_instance:
maxConnectionsPerInstance:
description:
- The max number of simultaneous connections that a single backend instance can handle.
This is used to calculate the capacity of the group. Can be used in either CONNECTION
@ -378,7 +383,7 @@ RETURN = '''
- This cannot be used for internal load balancing.
returned: success
type: int
max_rate:
maxRate:
description:
- The max requests per second (RPS) of the group.
- Can be used with either RATE or UTILIZATION balancing modes, but required if RATE
@ -386,7 +391,7 @@ RETURN = '''
- This cannot be used for internal load balancing.
returned: success
type: int
max_rate_per_instance:
maxRatePerInstance:
description:
- The max requests per second (RPS) that a single backend instance can handle. This
is used to calculate the capacity of the group. Can be used in either balancing
@ -394,43 +399,43 @@ RETURN = '''
- This cannot be used for internal load balancing.
returned: success
type: str
max_utilization:
maxUtilization:
description:
- Used when balancingMode is UTILIZATION. This ratio defines the CPU utilization target
for the group. The default is 0.8. Valid range is [0.0, 1.0].
- This cannot be used for internal load balancing.
returned: success
type: str
cdn_policy:
cdnPolicy:
description:
- Cloud CDN configuration for this BackendService.
returned: success
type: complex
contains:
cache_key_policy:
cacheKeyPolicy:
description:
- The CacheKeyPolicy for this CdnPolicy.
returned: success
type: complex
contains:
include_host:
includeHost:
description:
- If true requests to different hosts will be cached separately.
returned: success
type: bool
include_protocol:
includeProtocol:
description:
- If true, http and https requests will be cached separately.
returned: success
type: bool
include_query_string:
includeQueryString:
description:
- If true, include query string parameters in the cache key according to query_string_whitelist
and query_string_blacklist. If neither is set, the entire query string will be included.
- If false, the query string will be excluded from the cache key entirely.
returned: success
type: bool
query_string_blacklist:
queryStringBlacklist:
description:
- Names of query string parameters to exclude in cache keys.
- All other parameters will be included. Either specify query_string_whitelist or
@ -438,7 +443,7 @@ RETURN = '''
- "'&' and '=' will be percent encoded and not treated as delimiters."
returned: success
type: list
query_string_whitelist:
queryStringWhitelist:
description:
- Names of query string parameters to include in cache keys.
- All other parameters will be excluded. Either specify query_string_whitelist or
@ -446,19 +451,19 @@ RETURN = '''
- "'&' and '=' will be percent encoded and not treated as delimiters."
returned: success
type: list
connection_draining:
connectionDraining:
description:
- Settings for connection draining.
returned: success
type: complex
contains:
draining_timeout_sec:
drainingTimeoutSec:
description:
- Time for which instance will be drained (not accept new connections, but still work
to finish started).
returned: success
type: int
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -468,13 +473,13 @@ RETURN = '''
- An optional description of this resource.
returned: success
type: str
enable_cdn:
enableCDN:
description:
- If true, enable Cloud CDN for this BackendService.
- When the load balancing scheme is INTERNAL, this field is not used.
returned: success
type: bool
health_checks:
healthChecks:
description:
- The list of URLs to the HttpHealthCheck or HttpsHealthCheck resource for health
checking this BackendService. Currently at most one health check can be specified,
@ -498,22 +503,22 @@ RETURN = '''
- Enables IAP.
returned: success
type: bool
oauth2_client_id:
oauth2ClientId:
description:
- OAuth2 Client ID for IAP.
returned: success
type: str
oauth2_client_secret:
oauth2ClientSecret:
description:
- OAuth2 Client Secret for IAP.
returned: success
type: str
oauth2_client_secret_sha256:
oauth2ClientSecretSha256:
description:
- OAuth2 Client Secret SHA-256 for IAP.
returned: success
type: str
load_balancing_scheme:
loadBalancingScheme:
description:
- Indicates whether the backend service will be used with internal or external load
balancing. A backend service created for one type of load balancing cannot be used
@ -530,7 +535,7 @@ RETURN = '''
be a dash.
returned: success
type: str
port_name:
portName:
description:
- Name of backend port. The same name should appear in the instance groups referenced
by this service. Required when the load balancing scheme is EXTERNAL.
@ -551,7 +556,7 @@ RETURN = '''
- This field is not applicable to global backend services.
returned: success
type: str
session_affinity:
sessionAffinity:
description:
- Type of session affinity to use. The default is NONE.
- When the load balancing scheme is EXTERNAL, can be NONE, CLIENT_IP, or GENERATED_COOKIE.
@ -560,7 +565,7 @@ RETURN = '''
- When the protocol is UDP, this field is not used.
returned: success
type: str
timeout_sec:
timeoutSec:
description:
- How many seconds to wait for the backend before considering it a failed request.
Default is 30 seconds. Valid range is [1, 86400].
@ -643,7 +648,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -703,9 +709,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -716,9 +722,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/global/backendServices".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.

@ -56,7 +56,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -66,7 +66,7 @@ items:
returned: always
type: complex
contains:
affinity_cookie_ttl_sec:
affinityCookieTtlSec:
description:
- Lifetime of cookies in seconds if session_affinity is GENERATED_COOKIE. If set to
0, the cookie is non-persistent and lasts only until the end of the browser session
@ -80,7 +80,7 @@ items:
returned: success
type: complex
contains:
balancing_mode:
balancingMode:
description:
- Specifies the balancing mode for this backend.
- For global HTTP(S) or TCP/SSL load balancing, the default is UTILIZATION. Valid
@ -88,7 +88,7 @@ items:
- This cannot be used for internal load balancing.
returned: success
type: str
capacity_scaler:
capacityScaler:
description:
- A multiplier applied to the group's maximum servicing capacity (based on UTILIZATION,
RATE or CONNECTION).
@ -114,7 +114,7 @@ items:
be in a zone within the same region as the BackendService.
returned: success
type: dict
max_connections:
maxConnections:
description:
- The max number of simultaneous connections for the group. Can be used with either
CONNECTION or UTILIZATION balancing modes.
@ -123,7 +123,7 @@ items:
- This cannot be used for internal load balancing.
returned: success
type: int
max_connections_per_instance:
maxConnectionsPerInstance:
description:
- The max number of simultaneous connections that a single backend instance can handle.
This is used to calculate the capacity of the group. Can be used in either CONNECTION
@ -133,7 +133,7 @@ items:
- This cannot be used for internal load balancing.
returned: success
type: int
max_rate:
maxRate:
description:
- The max requests per second (RPS) of the group.
- Can be used with either RATE or UTILIZATION balancing modes, but required if RATE
@ -141,7 +141,7 @@ items:
- This cannot be used for internal load balancing.
returned: success
type: int
max_rate_per_instance:
maxRatePerInstance:
description:
- The max requests per second (RPS) that a single backend instance can handle. This
is used to calculate the capacity of the group. Can be used in either balancing
@ -149,43 +149,43 @@ items:
- This cannot be used for internal load balancing.
returned: success
type: str
max_utilization:
maxUtilization:
description:
- Used when balancingMode is UTILIZATION. This ratio defines the CPU utilization target
for the group. The default is 0.8. Valid range is [0.0, 1.0].
- This cannot be used for internal load balancing.
returned: success
type: str
cdn_policy:
cdnPolicy:
description:
- Cloud CDN configuration for this BackendService.
returned: success
type: complex
contains:
cache_key_policy:
cacheKeyPolicy:
description:
- The CacheKeyPolicy for this CdnPolicy.
returned: success
type: complex
contains:
include_host:
includeHost:
description:
- If true requests to different hosts will be cached separately.
returned: success
type: bool
include_protocol:
includeProtocol:
description:
- If true, http and https requests will be cached separately.
returned: success
type: bool
include_query_string:
includeQueryString:
description:
- If true, include query string parameters in the cache key according to query_string_whitelist
and query_string_blacklist. If neither is set, the entire query string will be included.
- If false, the query string will be excluded from the cache key entirely.
returned: success
type: bool
query_string_blacklist:
queryStringBlacklist:
description:
- Names of query string parameters to exclude in cache keys.
- All other parameters will be included. Either specify query_string_whitelist or
@ -193,7 +193,7 @@ items:
- "'&' and '=' will be percent encoded and not treated as delimiters."
returned: success
type: list
query_string_whitelist:
queryStringWhitelist:
description:
- Names of query string parameters to include in cache keys.
- All other parameters will be excluded. Either specify query_string_whitelist or
@ -201,19 +201,19 @@ items:
- "'&' and '=' will be percent encoded and not treated as delimiters."
returned: success
type: list
connection_draining:
connectionDraining:
description:
- Settings for connection draining.
returned: success
type: complex
contains:
draining_timeout_sec:
drainingTimeoutSec:
description:
- Time for which instance will be drained (not accept new connections, but still work
to finish started).
returned: success
type: int
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -223,13 +223,13 @@ items:
- An optional description of this resource.
returned: success
type: str
enable_cdn:
enableCDN:
description:
- If true, enable Cloud CDN for this BackendService.
- When the load balancing scheme is INTERNAL, this field is not used.
returned: success
type: bool
health_checks:
healthChecks:
description:
- The list of URLs to the HttpHealthCheck or HttpsHealthCheck resource for health
checking this BackendService. Currently at most one health check can be specified,
@ -242,6 +242,39 @@ items:
- The unique identifier for the resource.
returned: success
type: int
iap:
description:
- Settings for enabling Cloud Identity Aware Proxy.
returned: success
type: complex
contains:
enabled:
description:
- Enables IAP.
returned: success
type: bool
oauth2ClientId:
description:
- OAuth2 Client ID for IAP.
returned: success
type: str
oauth2ClientSecret:
description:
- OAuth2 Client Secret for IAP.
returned: success
type: str
oauth2ClientSecretSha256:
description:
- OAuth2 Client Secret SHA-256 for IAP.
returned: success
type: str
loadBalancingScheme:
description:
- Indicates whether the backend service will be used with internal or external load
balancing. A backend service created for one type of load balancing cannot be used
with the other.
returned: success
type: str
name:
description:
- Name of the resource. Provided by the client when the resource is created. The name
@ -252,7 +285,7 @@ items:
be a dash.
returned: success
type: str
port_name:
portName:
description:
- Name of backend port. The same name should appear in the instance groups referenced
by this service. Required when the load balancing scheme is EXTERNAL.
@ -273,7 +306,7 @@ items:
- This field is not applicable to global backend services.
returned: success
type: str
session_affinity:
sessionAffinity:
description:
- Type of session affinity to use. The default is NONE.
- When the load balancing scheme is EXTERNAL, can be NONE, CLIENT_IP, or GENERATED_COOKIE.
@ -282,7 +315,7 @@ items:
- When the protocol is UDP, this field is not used.
returned: success
type: str
timeout_sec:
timeoutSec:
description:
- How many seconds to wait for the backend before considering it a failed request.
Default is 30 seconds. Valid range is [1, 86400].
@ -304,7 +337,7 @@ import json
def main():
module = GcpModule(
argument_spec=dict(
filters=dict(type='list', elements='str'),
filters=dict(type='list', elements='str')
)
)

@ -155,6 +155,11 @@ options:
full URL to the resource. For example, the following are valid values: *
`U(https://www.googleapis.com/compute/v1/projects/project/global/snapshots/snapshot`)
* `projects/project/global/snapshots/snapshot` * `global/snapshots/snapshot` .'
- 'This field represents a link to a Snapshot resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_snapshot
task and then set this source_snapshot field to "{{ name-of-resource }}" Alternatively,
you can set this source_snapshot to a dictionary with the selfLink key where the
value is the selfLink of your Snapshot.'
required: false
source_snapshot_encryption_key:
description:
@ -187,13 +192,19 @@ EXAMPLES = '''
raw_key: SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=
zone: us-central1-a
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
creation_timestamp:
labelFingerprint:
description:
- The fingerprint used for optimistic locking of this resource. Used internally during
updates.
returned: success
type: str
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -209,12 +220,12 @@ RETURN = '''
- The unique identifier for the resource.
returned: success
type: int
last_attach_timestamp:
lastAttachTimestamp:
description:
- Last attach timestamp in RFC3339 text format.
returned: success
type: str
last_detach_timestamp:
lastDetachTimestamp:
description:
- Last dettach timestamp in RFC3339 text format.
returned: success
@ -239,7 +250,7 @@ RETURN = '''
be a dash.
returned: success
type: str
size_gb:
sizeGb:
description:
- Size of the persistent disk, specified in GB. You can specify this field when creating
a persistent disk using the sourceImage or sourceSnapshot parameter, or specify
@ -248,19 +259,19 @@ RETURN = '''
sizeGb must not be less than the size of the sourceImage or the size of the snapshot.
returned: success
type: int
type:
description:
- URL of the disk type resource describing which disk type to use to create the disk.
Provide this when creating the disk.
returned: success
type: str
users:
description:
- 'Links to the users of the disk (attached instances) in form: project/zones/zone/instances/instance
.'
returned: success
type: list
source_image:
type:
description:
- URL of the disk type resource describing which disk type to use to create the disk.
Provide this when creating the disk.
returned: success
type: str
sourceImage:
description:
- The source image used to create this disk. If the source image is deleted, this
field will not be set.
@ -280,14 +291,14 @@ RETURN = '''
- A reference to the zone where the disk resides.
returned: success
type: str
source_image_encryption_key:
sourceImageEncryptionKey:
description:
- The customer-supplied encryption key of the source image. Required if the source
image is protected by a customer-supplied encryption key.
returned: success
type: complex
contains:
raw_key:
rawKey:
description:
- Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64
to either encrypt or decrypt this resource.
@ -299,7 +310,7 @@ RETURN = '''
that protects this resource.
returned: success
type: str
source_image_id:
sourceImageId:
description:
- The ID value of the image used to create this disk. This value identifies the exact
image that was used to create this persistent disk. For example, if you created
@ -308,7 +319,7 @@ RETURN = '''
was used.
returned: success
type: str
disk_encryption_key:
diskEncryptionKey:
description:
- Encrypts the disk using a customer-supplied encryption key.
- After you encrypt a disk with a customer-supplied key, you must provide the same
@ -321,7 +332,7 @@ RETURN = '''
returned: success
type: complex
contains:
raw_key:
rawKey:
description:
- Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64
to either encrypt or decrypt this resource.
@ -333,7 +344,7 @@ RETURN = '''
that protects this resource.
returned: success
type: str
source_snapshot:
sourceSnapshot:
description:
- 'The source snapshot used to create this disk. You can provide this as a partial or
full URL to the resource. For example, the following are valid values: *
@ -341,14 +352,14 @@ RETURN = '''
* `projects/project/global/snapshots/snapshot` * `global/snapshots/snapshot` .'
returned: success
type: dict
source_snapshot_encryption_key:
sourceSnapshotEncryptionKey:
description:
- The customer-supplied encryption key of the source snapshot. Required if the source
snapshot is protected by a customer-supplied encryption key.
returned: success
type: complex
contains:
raw_key:
rawKey:
description:
- Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64
to either encrypt or decrypt this resource.
@ -360,7 +371,7 @@ RETURN = '''
that protects this resource.
returned: success
type: str
source_snapshot_id:
sourceSnapshotId:
description:
- The unique ID of the snapshot used to create this disk. This value identifies the
exact snapshot that was used to create this persistent disk. For example, if you
@ -427,7 +438,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind, fetch)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -450,8 +462,44 @@ def create(module, link, kind):
return wait_for_operation(module, auth.post(link, resource_to_request(module)))
def update(module, link, kind):
module.fail_json(msg="Disk cannot be edited")
def update(module, link, kind, fetch):
update_fields(module, resource_to_request(module),
response_to_hash(module, fetch))
return fetch_resource(module, self_link(module), kind)
def update_fields(module, request, response):
if response.get('labels') != request.get('labels'):
label_fingerprint_update(module, request, response)
if response.get('sizeGb') != request.get('sizeGb'):
size_gb_update(module, request, response)
def label_fingerprint_update(module, request, response):
auth = GcpSession(module, 'compute')
auth.post(
''.join([
"https://www.googleapis.com/compute/v1/",
"projects/{project}/zones/{zone}/disks/{name}/setLabels"
]).format(**module.params),
{
u'labelFingerprint': response.get('labelFingerprint'),
u'labels': module.params.get('labels')
}
)
def size_gb_update(module, request, response):
auth = GcpSession(module, 'compute')
auth.post(
''.join([
"https://www.googleapis.com/compute/v1/",
"projects/{project}/zones/{zone}/disks/{name}/resize"
]).format(**module.params),
{
u'sizeGb': module.params.get('size_gb')
}
)
def delete(module, link, kind):
@ -481,9 +529,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -494,9 +542,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/disks".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -511,8 +559,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result
@ -539,6 +585,7 @@ def is_different(module, response):
# This is for doing comparisons with Ansible's current parameters.
def response_to_hash(module, response):
return {
u'labelFingerprint': response.get(u'labelFingerprint'),
u'creationTimestamp': response.get(u'creationTimestamp'),
u'description': response.get(u'description'),
u'id': response.get(u'id'),
@ -548,8 +595,8 @@ def response_to_hash(module, response):
u'licenses': response.get(u'licenses'),
u'name': module.params.get('name'),
u'sizeGb': response.get(u'sizeGb'),
u'type': response.get(u'type'),
u'users': response.get(u'users'),
u'type': response.get(u'type'),
u'sourceImage': module.params.get('source_image')
}
@ -557,7 +604,7 @@ def response_to_hash(module, response):
def disk_type_selflink(name, params):
if name is None:
return
url = r"https://www.googleapis.com/compute/v1/projects/.*/zones/{zone}/diskTypes/[a-z1-9\-]*"
url = r"https://www.googleapis.com/compute/v1/projects/.*/zones/[a-z1-9\-]*/diskTypes/[a-z1-9\-]*"
if not re.match(url, name):
name = "https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/diskTypes/%s".format(**params) % name
return name

@ -61,7 +61,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -71,7 +71,13 @@ items:
returned: always
type: complex
contains:
creation_timestamp:
labelFingerprint:
description:
- The fingerprint used for optimistic locking of this resource. Used internally during
updates.
returned: success
type: str
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -87,12 +93,12 @@ items:
- The unique identifier for the resource.
returned: success
type: int
last_attach_timestamp:
lastAttachTimestamp:
description:
- Last attach timestamp in RFC3339 text format.
returned: success
type: str
last_detach_timestamp:
lastDetachTimestamp:
description:
- Last dettach timestamp in RFC3339 text format.
returned: success
@ -117,7 +123,7 @@ items:
be a dash.
returned: success
type: str
size_gb:
sizeGb:
description:
- Size of the persistent disk, specified in GB. You can specify this field when creating
a persistent disk using the sourceImage or sourceSnapshot parameter, or specify
@ -138,7 +144,7 @@ items:
Provide this when creating the disk.
returned: success
type: str
source_image:
sourceImage:
description:
- The source image used to create this disk. If the source image is deleted, this
field will not be set.
@ -158,14 +164,14 @@ items:
- A reference to the zone where the disk resides.
returned: success
type: str
source_image_encryption_key:
sourceImageEncryptionKey:
description:
- The customer-supplied encryption key of the source image. Required if the source
image is protected by a customer-supplied encryption key.
returned: success
type: complex
contains:
raw_key:
rawKey:
description:
- Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64
to either encrypt or decrypt this resource.
@ -177,7 +183,7 @@ items:
that protects this resource.
returned: success
type: str
source_image_id:
sourceImageId:
description:
- The ID value of the image used to create this disk. This value identifies the exact
image that was used to create this persistent disk. For example, if you created
@ -186,7 +192,7 @@ items:
was used.
returned: success
type: str
disk_encryption_key:
diskEncryptionKey:
description:
- Encrypts the disk using a customer-supplied encryption key.
- After you encrypt a disk with a customer-supplied key, you must provide the same
@ -199,7 +205,7 @@ items:
returned: success
type: complex
contains:
raw_key:
rawKey:
description:
- Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64
to either encrypt or decrypt this resource.
@ -211,7 +217,7 @@ items:
that protects this resource.
returned: success
type: str
source_snapshot:
sourceSnapshot:
description:
- 'The source snapshot used to create this disk. You can provide this as a partial
or full URL to the resource. For example, the following are valid values: *
@ -219,14 +225,14 @@ items:
* `projects/project/global/snapshots/snapshot` * `global/snapshots/snapshot` .'
returned: success
type: dict
source_snapshot_encryption_key:
sourceSnapshotEncryptionKey:
description:
- The customer-supplied encryption key of the source snapshot. Required if the source
snapshot is protected by a customer-supplied encryption key.
returned: success
type: complex
contains:
raw_key:
rawKey:
description:
- Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64
to either encrypt or decrypt this resource.
@ -238,7 +244,7 @@ items:
that protects this resource.
returned: success
type: str
source_snapshot_id:
sourceSnapshotId:
description:
- The unique ID of the snapshot used to create this disk. This value identifies the
exact snapshot that was used to create this persistent disk. For example, if you

@ -72,11 +72,55 @@ options:
specified, this rule applies to connections through any port.
- 'Example inputs include: ["22"], ["80","443"], and ["12345-12349"].'
required: false
denied:
description:
- The list of DENY rules specified by this firewall. Each rule specifies a protocol
and port-range tuple that describes a denied connection.
required: false
version_added: 2.8
suboptions:
ip_protocol:
description:
- The IP protocol to which this rule applies. The protocol type is required when creating
a firewall rule. This value can either be one of the following well known protocol
strings (tcp, udp, icmp, esp, ah, sctp), or the IP protocol number.
required: true
ports:
description:
- An optional list of ports to which this rule applies. This field is only applicable
for UDP or TCP protocol. Each entry must be either an integer or a range. If not
specified, this rule applies to connections through any port.
- 'Example inputs include: ["22"], ["80","443"], and ["12345-12349"].'
required: false
description:
description:
- An optional description of this resource. Provide this property when you create
the resource.
required: false
destination_ranges:
description:
- If destination ranges are specified, the firewall will apply only to traffic that
has destination IP address in these ranges. These ranges must be expressed in CIDR
format. Only IPv4 is supported.
required: false
version_added: 2.8
direction:
description:
- 'Direction of traffic to which this firewall applies; default is INGRESS. Note:
For INGRESS traffic, it is NOT supported to specify destinationRanges; For EGRESS
traffic, it is NOT supported to specify sourceRanges OR sourceTags.'
required: false
version_added: 2.8
choices: ['INGRESS', 'EGRESS']
disabled:
description:
- Denotes whether the firewall rule is disabled, i.e not applied to the network it
is associated with. When set to true, the firewall rule is not enforced and the
network behaves as if it did not exist. If this is unspecified, the firewall rule
will be enabled.
required: false
type: bool
version_added: 2.8
name:
description:
- Name of the resource. Provided by the client when the resource is created. The name
@ -85,7 +129,7 @@ options:
which means the first character must be a lowercase letter, and all following characters
must be a dash, lowercase letter, or digit, except the last character, which cannot
be a dash.
required: false
required: true
network:
description:
- 'URL of the network resource for this firewall rule. If not specified when creating
@ -95,7 +139,22 @@ options:
U(https://www.googleapis.com/compute/v1/projects/myproject/global/)
networks/my-network projects/myproject/global/networks/my-network
global/networks/default .'
- 'This field represents a link to a Network resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_network task
and then set this network field to "{{ name-of-resource }}" Alternatively, you can
set this network to a dictionary with the selfLink key where the value is the selfLink
of your Network.'
required: true
priority:
description:
- Priority for this rule. This is an integer between 0 and 65535, both inclusive.
When not specified, the value assumed is 1000. Relative priorities determine precedence
of conflicting rules. Lower value of priority implies higher precedence (eg, a rule
with priority 0 has higher precedence than a rule with priority 1). DENY rules take
precedence over ALLOW rules having equal priority.
required: false
default: 1000
version_added: 2.8
source_ranges:
description:
- If source ranges are specified, the firewall will apply only to traffic that has
@ -105,6 +164,19 @@ options:
OR the source IP that belongs to a tag listed in the sourceTags property. The connection
does not need to match both properties for the firewall to apply. Only IPv4 is supported.
required: false
source_service_accounts:
description:
- If source service accounts are specified, the firewall will apply only to traffic
originating from an instance with a service account in this list. Source service
accounts cannot be used to control traffic to an instance's external IP address
because service accounts are associated with an instance, not an IP address. sourceRanges
can be set at the same time as sourceServiceAccounts. If both are set, the firewall
will apply to traffic that has source IP address within sourceRanges OR the source
IP belongs to an instance with service account listed in sourceServiceAccount. The
connection does not need to match both properties for the firewall to apply. sourceServiceAccounts
cannot be used at the same time as sourceTags or targetTags.
required: false
version_added: 2.8
source_tags:
description:
- If source tags are specified, the firewall will apply only to traffic with source
@ -116,6 +188,15 @@ options:
sourceTags property. The connection does not need to match both properties for the
firewall to apply.
required: false
target_service_accounts:
description:
- A list of service accounts indicating sets of instances located in the network that
may make network connections as specified in allowed[].
- targetServiceAccounts cannot be used at the same time as targetTags or sourceTags.
If neither targetServiceAccounts nor targetTags are specified, the firewall rule
applies to all instances on the specified network.
required: false
version_added: 2.8
target_tags:
description:
- A list of instance tags indicating sets of instances located in the network that
@ -124,6 +205,9 @@ options:
specified network.
required: false
extends_documentation_fragment: gcp
notes:
- "API Reference: U(https://cloud.google.com/compute/docs/reference/latest/firewalls)"
- "Official Documentation: U(https://cloud.google.com/vpc/docs/firewalls)"
'''
EXAMPLES = '''
@ -140,7 +224,7 @@ EXAMPLES = '''
source_tags:
- test-ssh-clients
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
@ -168,17 +252,61 @@ RETURN = '''
- 'Example inputs include: ["22"], ["80","443"], and ["12345-12349"].'
returned: success
type: list
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
type: str
denied:
description:
- The list of DENY rules specified by this firewall. Each rule specifies a protocol
and port-range tuple that describes a denied connection.
returned: success
type: complex
contains:
ip_protocol:
description:
- The IP protocol to which this rule applies. The protocol type is required when creating
a firewall rule. This value can either be one of the following well known protocol
strings (tcp, udp, icmp, esp, ah, sctp), or the IP protocol number.
returned: success
type: str
ports:
description:
- An optional list of ports to which this rule applies. This field is only applicable
for UDP or TCP protocol. Each entry must be either an integer or a range. If not
specified, this rule applies to connections through any port.
- 'Example inputs include: ["22"], ["80","443"], and ["12345-12349"].'
returned: success
type: list
description:
description:
- An optional description of this resource. Provide this property when you create
the resource.
returned: success
type: str
destinationRanges:
description:
- If destination ranges are specified, the firewall will apply only to traffic that
has destination IP address in these ranges. These ranges must be expressed in CIDR
format. Only IPv4 is supported.
returned: success
type: list
direction:
description:
- 'Direction of traffic to which this firewall applies; default is INGRESS. Note:
For INGRESS traffic, it is NOT supported to specify destinationRanges; For EGRESS
traffic, it is NOT supported to specify sourceRanges OR sourceTags.'
returned: success
type: str
disabled:
description:
- Denotes whether the firewall rule is disabled, i.e not applied to the network it
is associated with. When set to true, the firewall rule is not enforced and the
network behaves as if it did not exist. If this is unspecified, the firewall rule
will be enabled.
returned: success
type: bool
id:
description:
- The unique identifier for the resource.
@ -204,8 +332,17 @@ RETURN = '''
networks/my-network projects/myproject/global/networks/my-network
global/networks/default .'
returned: success
type: str
source_ranges:
type: dict
priority:
description:
- Priority for this rule. This is an integer between 0 and 65535, both inclusive.
When not specified, the value assumed is 1000. Relative priorities determine precedence
of conflicting rules. Lower value of priority implies higher precedence (eg, a rule
with priority 0 has higher precedence than a rule with priority 1). DENY rules take
precedence over ALLOW rules having equal priority.
returned: success
type: int
sourceRanges:
description:
- If source ranges are specified, the firewall will apply only to traffic that has
source IP address in these ranges. These ranges must be expressed in CIDR format.
@ -215,7 +352,20 @@ RETURN = '''
does not need to match both properties for the firewall to apply. Only IPv4 is supported.
returned: success
type: list
source_tags:
sourceServiceAccounts:
description:
- If source service accounts are specified, the firewall will apply only to traffic
originating from an instance with a service account in this list. Source service
accounts cannot be used to control traffic to an instance's external IP address
because service accounts are associated with an instance, not an IP address. sourceRanges
can be set at the same time as sourceServiceAccounts. If both are set, the firewall
will apply to traffic that has source IP address within sourceRanges OR the source
IP belongs to an instance with service account listed in sourceServiceAccount. The
connection does not need to match both properties for the firewall to apply. sourceServiceAccounts
cannot be used at the same time as sourceTags or targetTags.
returned: success
type: list
sourceTags:
description:
- If source tags are specified, the firewall will apply only to traffic with source
IP that belongs to a tag listed in source tags. Source tags cannot be used to control
@ -227,7 +377,16 @@ RETURN = '''
firewall to apply.
returned: success
type: list
target_tags:
targetServiceAccounts:
description:
- A list of service accounts indicating sets of instances located in the network that
may make network connections as specified in allowed[].
- targetServiceAccounts cannot be used at the same time as targetTags or sourceTags.
If neither targetServiceAccounts nor targetTags are specified, the firewall rule
applies to all instances on the specified network.
returned: success
type: list
targetTags:
description:
- A list of instance tags indicating sets of instances located in the network that
may make network connections as specified in allowed[].
@ -260,11 +419,21 @@ def main():
ip_protocol=dict(required=True, type='str'),
ports=dict(type='list', elements='str')
)),
denied=dict(type='list', elements='dict', options=dict(
ip_protocol=dict(required=True, type='str'),
ports=dict(type='list', elements='str')
)),
description=dict(type='str'),
name=dict(type='str'),
network=dict(type='str'),
destination_ranges=dict(type='list', elements='str'),
direction=dict(type='str', choices=['INGRESS', 'EGRESS']),
disabled=dict(type='bool'),
name=dict(required=True, type='str'),
network=dict(required=True, type='dict'),
priority=dict(default=1000, type='int'),
source_ranges=dict(type='list', elements='str'),
source_service_accounts=dict(type='list', elements='str'),
source_tags=dict(type='list', elements='str'),
target_service_accounts=dict(type='list', elements='str'),
target_tags=dict(type='list', elements='str')
)
)
@ -281,7 +450,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -306,7 +476,7 @@ def create(module, link, kind):
def update(module, link, kind):
auth = GcpSession(module, 'compute')
return wait_for_operation(module, auth.put(link, resource_to_request(module)))
return wait_for_operation(module, auth.patch(link, resource_to_request(module)))
def delete(module, link, kind):
@ -318,11 +488,18 @@ def resource_to_request(module):
request = {
u'kind': 'compute#firewall',
u'allowed': FirewallAllowedArray(module.params.get('allowed', []), module).to_request(),
u'denied': FirewallDeniedArray(module.params.get('denied', []), module).to_request(),
u'description': module.params.get('description'),
u'destinationRanges': module.params.get('destination_ranges'),
u'direction': module.params.get('direction'),
u'disabled': module.params.get('disabled'),
u'name': module.params.get('name'),
u'network': module.params.get('network'),
u'network': replace_resource_dict(module.params.get(u'network', {}), 'selfLink'),
u'priority': module.params.get('priority'),
u'sourceRanges': module.params.get('source_ranges'),
u'sourceServiceAccounts': module.params.get('source_service_accounts'),
u'sourceTags': module.params.get('source_tags'),
u'targetServiceAccounts': module.params.get('target_service_accounts'),
u'targetTags': module.params.get('target_tags')
}
return_vals = {}
@ -333,9 +510,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -346,9 +523,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/global/firewalls".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -363,8 +540,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result
@ -393,12 +568,19 @@ def response_to_hash(module, response):
return {
u'allowed': FirewallAllowedArray(response.get(u'allowed', []), module).from_response(),
u'creationTimestamp': response.get(u'creationTimestamp'),
u'denied': FirewallDeniedArray(response.get(u'denied', []), module).from_response(),
u'description': response.get(u'description'),
u'destinationRanges': response.get(u'destinationRanges'),
u'direction': response.get(u'direction'),
u'disabled': response.get(u'disabled'),
u'id': response.get(u'id'),
u'name': response.get(u'name'),
u'name': module.params.get('name'),
u'network': response.get(u'network'),
u'priority': response.get(u'priority'),
u'sourceRanges': response.get(u'sourceRanges'),
u'sourceServiceAccounts': response.get(u'sourceServiceAccounts'),
u'sourceTags': response.get(u'sourceTags'),
u'targetServiceAccounts': response.get(u'targetServiceAccounts'),
u'targetTags': response.get(u'targetTags')
}
@ -473,5 +655,38 @@ class FirewallAllowedArray(object):
})
class FirewallDeniedArray(object):
def __init__(self, request, module):
self.module = module
if request:
self.request = request
else:
self.request = []
def to_request(self):
items = []
for item in self.request:
items.append(self._request_for_item(item))
return items
def from_response(self):
items = []
for item in self.request:
items.append(self._response_from_item(item))
return items
def _request_for_item(self, item):
return remove_nones_from_dict({
u'IPProtocol': item.get('ip_protocol'),
u'ports': item.get('ports')
})
def _response_from_item(self, item):
return remove_nones_from_dict({
u'IPProtocol': item.get(u'ip_protocol'),
u'ports': item.get(u'ports')
})
if __name__ == '__main__':
main()

@ -56,7 +56,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -88,17 +88,61 @@ items:
- 'Example inputs include: ["22"], ["80","443"], and ["12345-12349"].'
returned: success
type: list
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
type: str
denied:
description:
- The list of DENY rules specified by this firewall. Each rule specifies a protocol
and port-range tuple that describes a denied connection.
returned: success
type: complex
contains:
ip_protocol:
description:
- The IP protocol to which this rule applies. The protocol type is required when creating
a firewall rule. This value can either be one of the following well known protocol
strings (tcp, udp, icmp, esp, ah, sctp), or the IP protocol number.
returned: success
type: str
ports:
description:
- An optional list of ports to which this rule applies. This field is only applicable
for UDP or TCP protocol. Each entry must be either an integer or a range. If not
specified, this rule applies to connections through any port.
- 'Example inputs include: ["22"], ["80","443"], and ["12345-12349"].'
returned: success
type: list
description:
description:
- An optional description of this resource. Provide this property when you create
the resource.
returned: success
type: str
destinationRanges:
description:
- If destination ranges are specified, the firewall will apply only to traffic that
has destination IP address in these ranges. These ranges must be expressed in CIDR
format. Only IPv4 is supported.
returned: success
type: list
direction:
description:
- 'Direction of traffic to which this firewall applies; default is INGRESS. Note:
For INGRESS traffic, it is NOT supported to specify destinationRanges; For EGRESS
traffic, it is NOT supported to specify sourceRanges OR sourceTags.'
returned: success
type: str
disabled:
description:
- Denotes whether the firewall rule is disabled, i.e not applied to the network it
is associated with. When set to true, the firewall rule is not enforced and the
network behaves as if it did not exist. If this is unspecified, the firewall rule
will be enabled.
returned: success
type: bool
id:
description:
- The unique identifier for the resource.
@ -124,8 +168,17 @@ items:
networks/my-network projects/myproject/global/networks/my-network
global/networks/default .'
returned: success
type: str
source_ranges:
type: dict
priority:
description:
- Priority for this rule. This is an integer between 0 and 65535, both inclusive.
When not specified, the value assumed is 1000. Relative priorities determine precedence
of conflicting rules. Lower value of priority implies higher precedence (eg, a rule
with priority 0 has higher precedence than a rule with priority 1). DENY rules take
precedence over ALLOW rules having equal priority.
returned: success
type: int
sourceRanges:
description:
- If source ranges are specified, the firewall will apply only to traffic that has
source IP address in these ranges. These ranges must be expressed in CIDR format.
@ -135,7 +188,20 @@ items:
does not need to match both properties for the firewall to apply. Only IPv4 is supported.
returned: success
type: list
source_tags:
sourceServiceAccounts:
description:
- If source service accounts are specified, the firewall will apply only to traffic
originating from an instance with a service account in this list. Source service
accounts cannot be used to control traffic to an instance's external IP address
because service accounts are associated with an instance, not an IP address. sourceRanges
can be set at the same time as sourceServiceAccounts. If both are set, the firewall
will apply to traffic that has source IP address within sourceRanges OR the source
IP belongs to an instance with service account listed in sourceServiceAccount. The
connection does not need to match both properties for the firewall to apply. sourceServiceAccounts
cannot be used at the same time as sourceTags or targetTags.
returned: success
type: list
sourceTags:
description:
- If source tags are specified, the firewall will apply only to traffic with source
IP that belongs to a tag listed in source tags. Source tags cannot be used to control
@ -147,7 +213,16 @@ items:
firewall to apply.
returned: success
type: list
target_tags:
targetServiceAccounts:
description:
- A list of service accounts indicating sets of instances located in the network that
may make network connections as specified in allowed[].
- targetServiceAccounts cannot be used at the same time as targetTags or sourceTags.
If neither targetServiceAccounts nor targetTags are specified, the firewall rule
applies to all instances on the specified network.
returned: success
type: list
targetTags:
description:
- A list of instance tags indicating sets of instances located in the network that
may make network connections as specified in allowed[].
@ -171,7 +246,7 @@ import json
def main():
module = GcpModule(
argument_spec=dict(
filters=dict(type='list', elements='str'),
filters=dict(type='list', elements='str')
)
)

@ -85,6 +85,11 @@ options:
- A reference to a BackendService to receive the matched traffic.
- This is used for internal load balancing.
- "(not used for external load balancing) ."
- 'This field represents a link to a BackendService resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_backend_service
task and then set this backend_service field to "{{ name-of-resource }}" Alternatively,
you can set this backend_service to a dictionary with the selfLink key where the
value is the selfLink of your BackendService.'
required: false
ip_version:
description:
@ -116,6 +121,11 @@ options:
IP should belong to for this Forwarding Rule. If this field is not specified, the
default network will be used.
- This field is not used for external load balancing.
- 'This field represents a link to a Network resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_network task
and then set this network field to "{{ name-of-resource }}" Alternatively, you can
set this network to a dictionary with the selfLink key where the value is the selfLink
of your Network.'
required: false
port_range:
description:
@ -147,6 +157,11 @@ options:
- If the network specified is in auto subnet mode, this field is optional. However,
if the network is in custom subnet mode, a subnetwork must be specified.
- This field is not used for external load balancing.
- 'This field represents a link to a Subnetwork resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_subnetwork
task and then set this subnetwork field to "{{ name-of-resource }}" Alternatively,
you can set this subnetwork to a dictionary with the selfLink key where the value
is the selfLink of your Subnetwork.'
required: false
target:
description:
@ -155,8 +170,21 @@ options:
rule. For global forwarding rules, this target must be a global load balancing resource.
The forwarded traffic must be of a type appropriate to the target object.
- This field is not used for internal load balancing.
- 'This field represents a link to a TargetPool resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_target_pool
task and then set this target field to "{{ name-of-resource }}" Alternatively, you
can set this target to a dictionary with the selfLink key where the value is the
selfLink of your TargetPool.'
required: false
version_added: 2.7
network_tier:
description:
- 'The networking tier used for configuring this address. This field can take the
following values: PREMIUM or STANDARD. If this field is not specified, it is assumed
to be PREMIUM.'
required: false
version_added: 2.8
choices: ['PREMIUM', 'STANDARD']
region:
description:
- A reference to the region where the regional forwarding rule resides.
@ -198,13 +226,13 @@ EXAMPLES = '''
port_range: 80-80
ip_address: "{{ address.address }}"
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -220,7 +248,7 @@ RETURN = '''
- The unique identifier for the resource.
returned: success
type: int
ip_address:
IPAddress:
description:
- The IP address that this forwarding rule is serving on behalf of.
- Addresses are restricted based on the forwarding rule's load balancing scheme (EXTERNAL
@ -241,27 +269,27 @@ RETURN = '''
* global/addresses/address * address .'
returned: success
type: str
ip_protocol:
IPProtocol:
description:
- The IP protocol to which this rule applies. Valid options are TCP, UDP, ESP, AH,
SCTP or ICMP.
- When the load balancing scheme is INTERNAL, only TCP and UDP are valid.
returned: success
type: str
backend_service:
backendService:
description:
- A reference to a BackendService to receive the matched traffic.
- This is used for internal load balancing.
- "(not used for external load balancing) ."
returned: success
type: dict
ip_version:
ipVersion:
description:
- The IP Version that will be used by this forwarding rule. Valid options are IPV4
or IPV6. This can only be specified for a global forwarding rule.
returned: success
type: str
load_balancing_scheme:
loadBalancingScheme:
description:
- 'This signifies what the ForwardingRule will be used for and can only take the following
values: INTERNAL, EXTERNAL The value of INTERNAL means that this will be used for
@ -288,7 +316,7 @@ RETURN = '''
- This field is not used for external load balancing.
returned: success
type: dict
port_range:
portRange:
description:
- This field is used along with the target field for TargetHttpProxy, TargetHttpsProxy,
TargetSslProxy, TargetTcpProxy, TargetVpnGateway, TargetPool, TargetInstance.
@ -331,6 +359,19 @@ RETURN = '''
- This field is not used for internal load balancing.
returned: success
type: dict
labelFingerprint:
description:
- The fingerprint used for optimistic locking of this resource. Used internally during
updates.
returned: success
type: str
networkTier:
description:
- 'The networking tier used for configuring this address. This field can take the
following values: PREMIUM or STANDARD. If this field is not specified, it is assumed
to be PREMIUM.'
returned: success
type: str
region:
description:
- A reference to the region where the regional forwarding rule resides.
@ -370,6 +411,7 @@ def main():
ports=dict(type='list', elements='str'),
subnetwork=dict(type='dict'),
target=dict(type='dict'),
network_tier=dict(type='str', choices=['PREMIUM', 'STANDARD']),
region=dict(required=True, type='str')
)
)
@ -386,7 +428,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind, fetch)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -409,9 +452,41 @@ def create(module, link, kind):
return wait_for_operation(module, auth.post(link, resource_to_request(module)))
def update(module, link, kind):
def update(module, link, kind, fetch):
update_fields(module, resource_to_request(module),
response_to_hash(module, fetch))
return fetch_resource(module, self_link(module), kind)
def update_fields(module, request, response):
if response.get('target') != request.get('target'):
target_update(module, request, response)
def target_update(module, request, response):
auth = GcpSession(module, 'compute')
return wait_for_operation(module, auth.put(link, resource_to_request(module)))
auth.post(
''.join([
"https://www.googleapis.com/compute/v1/",
"projects/{project}/regions/{region}/forwardingRules/{name}/setTarget"
]).format(**module.params),
{
u'target': replace_resource_dict(module.params.get(u'target', {}), 'selfLink')
}
)
def label_fingerprint_update(module, request, response):
auth = GcpSession(module, 'compute')
auth.post(
''.join([
"https://www.googleapis.com/compute/v1/",
"projects/{project}/regions/{region}/forwardingRules/{name}/setLabels"
]).format(**module.params),
{
u'labelFingerprint': response.get('labelFingerprint')
}
)
def delete(module, link, kind):
@ -433,7 +508,8 @@ def resource_to_request(module):
u'portRange': module.params.get('port_range'),
u'ports': module.params.get('ports'),
u'subnetwork': replace_resource_dict(module.params.get(u'subnetwork', {}), 'selfLink'),
u'target': replace_resource_dict(module.params.get(u'target', {}), 'selfLink')
u'target': replace_resource_dict(module.params.get(u'target', {}), 'selfLink'),
u'networkTier': module.params.get('network_tier')
}
return_vals = {}
for k, v in request.items():
@ -443,9 +519,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -456,9 +532,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/regions/{region}/forwardingRules".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -473,8 +549,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result
@ -514,7 +588,9 @@ def response_to_hash(module, response):
u'portRange': response.get(u'portRange'),
u'ports': response.get(u'ports'),
u'subnetwork': response.get(u'subnetwork'),
u'target': response.get(u'target')
u'target': response.get(u'target'),
u'labelFingerprint': response.get(u'labelFingerprint'),
u'networkTier': module.params.get('network_tier')
}

@ -62,7 +62,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -72,7 +72,7 @@ items:
returned: always
type: complex
contains:
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -88,7 +88,7 @@ items:
- The unique identifier for the resource.
returned: success
type: int
ip_address:
IPAddress:
description:
- The IP address that this forwarding rule is serving on behalf of.
- Addresses are restricted based on the forwarding rule's load balancing scheme (EXTERNAL
@ -109,27 +109,27 @@ items:
* global/addresses/address * address .'
returned: success
type: str
ip_protocol:
IPProtocol:
description:
- The IP protocol to which this rule applies. Valid options are TCP, UDP, ESP, AH,
SCTP or ICMP.
- When the load balancing scheme is INTERNAL, only TCP and UDP are valid.
returned: success
type: str
backend_service:
backendService:
description:
- A reference to a BackendService to receive the matched traffic.
- This is used for internal load balancing.
- "(not used for external load balancing) ."
returned: success
type: dict
ip_version:
ipVersion:
description:
- The IP Version that will be used by this forwarding rule. Valid options are IPV4
or IPV6. This can only be specified for a global forwarding rule.
returned: success
type: str
load_balancing_scheme:
loadBalancingScheme:
description:
- 'This signifies what the ForwardingRule will be used for and can only take the following
values: INTERNAL, EXTERNAL The value of INTERNAL means that this will be used for
@ -156,7 +156,7 @@ items:
- This field is not used for external load balancing.
returned: success
type: dict
port_range:
portRange:
description:
- This field is used along with the target field for TargetHttpProxy, TargetHttpsProxy,
TargetSslProxy, TargetTcpProxy, TargetVpnGateway, TargetPool, TargetInstance.
@ -199,6 +199,19 @@ items:
- This field is not used for internal load balancing.
returned: success
type: dict
labelFingerprint:
description:
- The fingerprint used for optimistic locking of this resource. Used internally during
updates.
returned: success
type: str
networkTier:
description:
- 'The networking tier used for configuring this address. This field can take the
following values: PREMIUM or STANDARD. If this field is not specified, it is assumed
to be PREMIUM.'
returned: success
type: str
region:
description:
- A reference to the region where the regional forwarding rule resides.

@ -67,6 +67,15 @@ options:
The default value is IPV4.
required: false
choices: ['IPV4', 'IPV6']
address_type:
description:
- The type of the address to reserve, default is EXTERNAL.
- "* EXTERNAL indicates public/external single IP address."
- "* INTERNAL indicates internal IP ranges belonging to some network."
required: false
default: EXTERNAL
version_added: 2.8
choices: ['EXTERNAL', 'INTERNAL']
extends_documentation_fragment: gcp
notes:
- "API Reference: U(https://cloud.google.com/compute/docs/reference/latest/globalAddresses)"
@ -78,7 +87,7 @@ EXAMPLES = '''
gcp_compute_global_address:
name: "test_object"
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
@ -89,7 +98,7 @@ RETURN = '''
- The static external IP address represented by this resource.
returned: success
type: str
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -115,7 +124,13 @@ RETURN = '''
be a dash.
returned: success
type: str
ip_version:
labelFingerprint:
description:
- The fingerprint used for optimistic locking of this resource. Used internally during
updates.
returned: success
type: str
ipVersion:
description:
- The IP Version that will be used by this address. Valid options are IPV4 or IPV6.
The default value is IPV4.
@ -126,6 +141,13 @@ RETURN = '''
- A reference to the region where the regional address resides.
returned: success
type: str
addressType:
description:
- The type of the address to reserve, default is EXTERNAL.
- "* EXTERNAL indicates public/external single IP address."
- "* INTERNAL indicates internal IP ranges belonging to some network."
returned: success
type: str
'''
################################################################################
@ -150,7 +172,8 @@ def main():
state=dict(default='present', choices=['present', 'absent'], type='str'),
description=dict(type='str'),
name=dict(required=True, type='str'),
ip_version=dict(type='str', choices=['IPV4', 'IPV6'])
ip_version=dict(type='str', choices=['IPV4', 'IPV6']),
address_type=dict(default='EXTERNAL', type='str', choices=['EXTERNAL', 'INTERNAL'])
)
)
@ -166,7 +189,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind, fetch)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -189,9 +213,27 @@ def create(module, link, kind):
return wait_for_operation(module, auth.post(link, resource_to_request(module)))
def update(module, link, kind):
def update(module, link, kind, fetch):
update_fields(module, resource_to_request(module),
response_to_hash(module, fetch))
return fetch_resource(module, self_link(module), kind)
def update_fields(module, request, response):
pass
def label_fingerprint_update(module, request, response):
auth = GcpSession(module, 'compute')
return wait_for_operation(module, auth.put(link, resource_to_request(module)))
auth.post(
''.join([
"https://www.googleapis.com/compute/v1/",
"projects/{project}/global/addresses/{name}/setLabels"
]).format(**module.params),
{
u'labelFingerprint': response.get('labelFingerprint')
}
)
def delete(module, link, kind):
@ -204,7 +246,8 @@ def resource_to_request(module):
u'kind': 'compute#address',
u'description': module.params.get('description'),
u'name': module.params.get('name'),
u'ipVersion': module.params.get('ip_version')
u'ipVersion': module.params.get('ip_version'),
u'addressType': module.params.get('address_type')
}
return_vals = {}
for k, v in request.items():
@ -214,9 +257,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -227,9 +270,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/global/addresses".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -244,8 +287,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result
@ -277,8 +318,10 @@ def response_to_hash(module, response):
u'description': response.get(u'description'),
u'id': response.get(u'id'),
u'name': response.get(u'name'),
u'labelFingerprint': response.get(u'labelFingerprint'),
u'ipVersion': response.get(u'ipVersion'),
u'region': response.get(u'region')
u'region': response.get(u'region'),
u'addressType': response.get(u'addressType')
}

@ -56,7 +56,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -71,7 +71,7 @@ items:
- The static external IP address represented by this resource.
returned: success
type: str
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -97,7 +97,13 @@ items:
be a dash.
returned: success
type: str
ip_version:
labelFingerprint:
description:
- The fingerprint used for optimistic locking of this resource. Used internally during
updates.
returned: success
type: str
ipVersion:
description:
- The IP Version that will be used by this address. Valid options are IPV4 or IPV6.
The default value is IPV4.
@ -108,6 +114,13 @@ items:
- A reference to the region where the regional address resides.
returned: success
type: str
addressType:
description:
- The type of the address to reserve, default is EXTERNAL.
- "* EXTERNAL indicates public/external single IP address."
- "* INTERNAL indicates internal IP ranges belonging to some network."
returned: success
type: str
'''
################################################################################
@ -124,7 +137,7 @@ import json
def main():
module = GcpModule(
argument_spec=dict(
filters=dict(type='list', elements='str'),
filters=dict(type='list', elements='str')
)
)

@ -87,6 +87,11 @@ options:
- A reference to a BackendService to receive the matched traffic.
- This is used for internal load balancing.
- "(not used for external load balancing) ."
- 'This field represents a link to a BackendService resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_backend_service
task and then set this backend_service field to "{{ name-of-resource }}" Alternatively,
you can set this backend_service to a dictionary with the selfLink key where the
value is the selfLink of your BackendService.'
required: false
ip_version:
description:
@ -118,6 +123,11 @@ options:
IP should belong to for this Forwarding Rule. If this field is not specified, the
default network will be used.
- This field is not used for external load balancing.
- 'This field represents a link to a Network resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_network task
and then set this network field to "{{ name-of-resource }}" Alternatively, you can
set this network to a dictionary with the selfLink key where the value is the selfLink
of your Network.'
required: false
port_range:
description:
@ -149,6 +159,11 @@ options:
- If the network specified is in auto subnet mode, this field is optional. However,
if the network is in custom subnet mode, a subnetwork must be specified.
- This field is not used for external load balancing.
- 'This field represents a link to a Subnetwork resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_subnetwork
task and then set this subnetwork field to "{{ name-of-resource }}" Alternatively,
you can set this subnetwork to a dictionary with the selfLink key where the value
is the selfLink of your Subnetwork.'
required: false
target:
description:
@ -234,13 +249,13 @@ EXAMPLES = '''
port_range: 80-80
target: "{{ httpproxy.selfLink }}"
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -256,7 +271,7 @@ RETURN = '''
- The unique identifier for the resource.
returned: success
type: int
ip_address:
IPAddress:
description:
- The IP address that this forwarding rule is serving on behalf of.
- Addresses are restricted based on the forwarding rule's load balancing scheme (EXTERNAL
@ -277,27 +292,27 @@ RETURN = '''
* global/addresses/address * address .'
returned: success
type: str
ip_protocol:
IPProtocol:
description:
- The IP protocol to which this rule applies. Valid options are TCP, UDP, ESP, AH,
SCTP or ICMP.
- When the load balancing scheme is INTERNAL, only TCP and UDP are valid.
returned: success
type: str
backend_service:
backendService:
description:
- A reference to a BackendService to receive the matched traffic.
- This is used for internal load balancing.
- "(not used for external load balancing) ."
returned: success
type: dict
ip_version:
ipVersion:
description:
- The IP Version that will be used by this forwarding rule. Valid options are IPV4
or IPV6. This can only be specified for a global forwarding rule.
returned: success
type: str
load_balancing_scheme:
loadBalancingScheme:
description:
- 'This signifies what the ForwardingRule will be used for and can only take the following
values: INTERNAL, EXTERNAL The value of INTERNAL means that this will be used for
@ -324,7 +339,7 @@ RETURN = '''
- This field is not used for external load balancing.
returned: success
type: dict
port_range:
portRange:
description:
- This field is used along with the target field for TargetHttpProxy, TargetHttpsProxy,
TargetSslProxy, TargetTcpProxy, TargetVpnGateway, TargetPool, TargetInstance.
@ -419,7 +434,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -476,9 +492,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -489,9 +505,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/global/forwardingRules".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -506,8 +522,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result

@ -56,7 +56,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -66,7 +66,7 @@ items:
returned: always
type: complex
contains:
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -82,7 +82,7 @@ items:
- The unique identifier for the resource.
returned: success
type: int
ip_address:
IPAddress:
description:
- The IP address that this forwarding rule is serving on behalf of.
- Addresses are restricted based on the forwarding rule's load balancing scheme (EXTERNAL
@ -103,27 +103,27 @@ items:
* global/addresses/address * address .'
returned: success
type: str
ip_protocol:
IPProtocol:
description:
- The IP protocol to which this rule applies. Valid options are TCP, UDP, ESP, AH,
SCTP or ICMP.
- When the load balancing scheme is INTERNAL, only TCP and UDP are valid.
returned: success
type: str
backend_service:
backendService:
description:
- A reference to a BackendService to receive the matched traffic.
- This is used for internal load balancing.
- "(not used for external load balancing) ."
returned: success
type: dict
ip_version:
ipVersion:
description:
- The IP Version that will be used by this forwarding rule. Valid options are IPV4
or IPV6. This can only be specified for a global forwarding rule.
returned: success
type: str
load_balancing_scheme:
loadBalancingScheme:
description:
- 'This signifies what the ForwardingRule will be used for and can only take the following
values: INTERNAL, EXTERNAL The value of INTERNAL means that this will be used for
@ -150,7 +150,7 @@ items:
- This field is not used for external load balancing.
returned: success
type: dict
port_range:
portRange:
description:
- This field is used along with the target field for TargetHttpProxy, TargetHttpsProxy,
TargetSslProxy, TargetTcpProxy, TargetVpnGateway, TargetPool, TargetInstance.
@ -213,7 +213,7 @@ import json
def main():
module = GcpModule(
argument_spec=dict(
filters=dict(type='list', elements='str'),
filters=dict(type='list', elements='str')
)
)

@ -32,8 +32,15 @@ DOCUMENTATION = '''
---
module: gcp_compute_health_check
description:
- An HealthCheck resource. This resource defines a template for how individual virtual
machines should be checked for health, via one of the supported protocols.
- Health Checks determine whether instances are responsive and able to do work.
- They are an important part of a comprehensive load balancing configuration, as they
enable monitoring instances behind load balancers.
- Health Checks poll instances at a specified interval. Instances that do not respond
successfully to some number of probes in a row are marked as unhealthy. No new connections
are sent to unhealthy instances, though existing connections will continue. The
health check will continue to poll unhealthy instances. If an instance later responds
successfully to some number of consecutive probes, it is marked healthy again and
can receive new connections.
short_description: Creates a GCP HealthCheck
version_added: 2.6
author: Google Inc. (@googlecloudplatform)
@ -62,6 +69,7 @@ options:
- A so-far unhealthy instance will be marked healthy after this many consecutive successes.
The default value is 2.
required: false
default: 2
name:
description:
- Name of the resource. Provided by the client when the resource is created. The name
@ -70,7 +78,7 @@ options:
which means the first character must be a lowercase letter, and all following characters
must be a dash, lowercase letter, or digit, except the last character, which cannot
be a dash.
required: false
required: true
timeout_sec:
description:
- How long (in seconds) to wait before claiming failure.
@ -91,7 +99,7 @@ options:
the default is TCP. Exactly one of the protocol-specific health check field must
be specified, which must match type field.
required: false
choices: ['TCP', 'SSL', 'HTTP']
choices: ['TCP', 'SSL', 'HTTP', 'HTTPS']
http_health_check:
description:
- A nested object resource.
@ -108,6 +116,7 @@ options:
- The request path of the HTTP health check request.
- The default value is /.
required: false
default: /
port:
description:
- The TCP port number for the HTTP health check request.
@ -123,6 +132,7 @@ options:
- Specifies the type of proxy header to append before sending data to the backend,
either NONE or PROXY_V1. The default is NONE.
required: false
default: NONE
choices: ['NONE', 'PROXY_V1']
https_health_check:
description:
@ -140,6 +150,7 @@ options:
- The request path of the HTTPS health check request.
- The default value is /.
required: false
default: /
port:
description:
- The TCP port number for the HTTPS health check request.
@ -155,6 +166,7 @@ options:
- Specifies the type of proxy header to append before sending data to the backend,
either NONE or PROXY_V1. The default is NONE.
required: false
default: NONE
choices: ['NONE', 'PROXY_V1']
tcp_health_check:
description:
@ -188,6 +200,7 @@ options:
- Specifies the type of proxy header to append before sending data to the backend,
either NONE or PROXY_V1. The default is NONE.
required: false
default: NONE
choices: ['NONE', 'PROXY_V1']
ssl_health_check:
description:
@ -221,8 +234,12 @@ options:
- Specifies the type of proxy header to append before sending data to the backend,
either NONE or PROXY_V1. The default is NONE.
required: false
default: NONE
choices: ['NONE', 'PROXY_V1']
extends_documentation_fragment: gcp
notes:
- "API Reference: U(https://cloud.google.com/compute/docs/reference/rest/latest/healthChecks)"
- "Official Documentation: U(https://cloud.google.com/load-balancing/docs/health-checks)"
'''
EXAMPLES = '''
@ -238,18 +255,18 @@ EXAMPLES = '''
timeout_sec: 2
unhealthy_threshold: 5
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
check_interval_sec:
checkIntervalSec:
description:
- How often (in seconds) to send a health check. The default value is 5 seconds.
returned: success
type: int
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -260,7 +277,7 @@ RETURN = '''
the resource.
returned: success
type: str
healthy_threshold:
healthyThreshold:
description:
- A so-far unhealthy instance will be marked healthy after this many consecutive successes.
The default value is 2.
@ -281,14 +298,14 @@ RETURN = '''
be a dash.
returned: success
type: str
timeout_sec:
timeoutSec:
description:
- How long (in seconds) to wait before claiming failure.
- The default value is 5 seconds. It is invalid for timeoutSec to have greater value
than checkIntervalSec.
returned: success
type: int
unhealthy_threshold:
unhealthyThreshold:
description:
- A so-far healthy instance will be marked unhealthy after this many consecutive failures.
The default value is 2.
@ -301,7 +318,7 @@ RETURN = '''
be specified, which must match type field.
returned: success
type: str
http_health_check:
httpHealthCheck:
description:
- A nested object resource.
returned: success
@ -314,7 +331,7 @@ RETURN = '''
is performed will be used.
returned: success
type: str
request_path:
requestPath:
description:
- The request path of the HTTP health check request.
- The default value is /.
@ -326,19 +343,19 @@ RETURN = '''
- The default value is 80.
returned: success
type: int
port_name:
portName:
description:
- Port name as defined in InstanceGroup#NamedPort#name. If both port and port_name
are defined, port takes precedence.
returned: success
type: str
proxy_header:
proxyHeader:
description:
- Specifies the type of proxy header to append before sending data to the backend,
either NONE or PROXY_V1. The default is NONE.
returned: success
type: str
https_health_check:
httpsHealthCheck:
description:
- A nested object resource.
returned: success
@ -351,7 +368,7 @@ RETURN = '''
is performed will be used.
returned: success
type: str
request_path:
requestPath:
description:
- The request path of the HTTPS health check request.
- The default value is /.
@ -363,19 +380,19 @@ RETURN = '''
- The default value is 443.
returned: success
type: int
port_name:
portName:
description:
- Port name as defined in InstanceGroup#NamedPort#name. If both port and port_name
are defined, port takes precedence.
returned: success
type: str
proxy_header:
proxyHeader:
description:
- Specifies the type of proxy header to append before sending data to the backend,
either NONE or PROXY_V1. The default is NONE.
returned: success
type: str
tcp_health_check:
tcpHealthCheck:
description:
- A nested object resource.
returned: success
@ -401,19 +418,19 @@ RETURN = '''
- The default value is 443.
returned: success
type: int
port_name:
portName:
description:
- Port name as defined in InstanceGroup#NamedPort#name. If both port and port_name
are defined, port takes precedence.
returned: success
type: str
proxy_header:
proxyHeader:
description:
- Specifies the type of proxy header to append before sending data to the backend,
either NONE or PROXY_V1. The default is NONE.
returned: success
type: str
ssl_health_check:
sslHealthCheck:
description:
- A nested object resource.
returned: success
@ -439,13 +456,13 @@ RETURN = '''
- The default value is 443.
returned: success
type: int
port_name:
portName:
description:
- Port name as defined in InstanceGroup#NamedPort#name. If both port and port_name
are defined, port takes precedence.
returned: success
type: str
proxy_header:
proxyHeader:
description:
- Specifies the type of proxy header to append before sending data to the backend,
either NONE or PROXY_V1. The default is NONE.
@ -474,38 +491,38 @@ def main():
state=dict(default='present', choices=['present', 'absent'], type='str'),
check_interval_sec=dict(default=5, type='int'),
description=dict(type='str'),
healthy_threshold=dict(type='int'),
name=dict(type='str'),
healthy_threshold=dict(default=2, type='int'),
name=dict(required=True, type='str'),
timeout_sec=dict(default=5, type='int', aliases=['timeout_seconds']),
unhealthy_threshold=dict(default=2, type='int'),
type=dict(type='str', choices=['TCP', 'SSL', 'HTTP']),
type=dict(type='str', choices=['TCP', 'SSL', 'HTTP', 'HTTPS']),
http_health_check=dict(type='dict', options=dict(
host=dict(type='str'),
request_path=dict(type='str'),
request_path=dict(default='/', type='str'),
port=dict(type='int'),
port_name=dict(type='str'),
proxy_header=dict(type='str', choices=['NONE', 'PROXY_V1'])
proxy_header=dict(default='NONE', type='str', choices=['NONE', 'PROXY_V1'])
)),
https_health_check=dict(type='dict', options=dict(
host=dict(type='str'),
request_path=dict(type='str'),
request_path=dict(default='/', type='str'),
port=dict(type='int'),
port_name=dict(type='str'),
proxy_header=dict(type='str', choices=['NONE', 'PROXY_V1'])
proxy_header=dict(default='NONE', type='str', choices=['NONE', 'PROXY_V1'])
)),
tcp_health_check=dict(type='dict', options=dict(
request=dict(type='str'),
response=dict(type='str'),
port=dict(type='int'),
port_name=dict(type='str'),
proxy_header=dict(type='str', choices=['NONE', 'PROXY_V1'])
proxy_header=dict(default='NONE', type='str', choices=['NONE', 'PROXY_V1'])
)),
ssl_health_check=dict(type='dict', options=dict(
request=dict(type='str'),
response=dict(type='str'),
port=dict(type='int'),
port_name=dict(type='str'),
proxy_header=dict(type='str', choices=['NONE', 'PROXY_V1'])
proxy_header=dict(default='NONE', type='str', choices=['NONE', 'PROXY_V1'])
))
)
)
@ -522,7 +539,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -578,9 +596,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -591,9 +609,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/global/healthChecks".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -608,8 +626,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result
@ -641,7 +657,7 @@ def response_to_hash(module, response):
u'description': response.get(u'description'),
u'healthyThreshold': response.get(u'healthyThreshold'),
u'id': response.get(u'id'),
u'name': response.get(u'name'),
u'name': module.params.get('name'),
u'timeoutSec': response.get(u'timeoutSec'),
u'unhealthyThreshold': response.get(u'unhealthyThreshold'),
u'type': response.get(u'type'),

@ -56,7 +56,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -66,12 +66,12 @@ items:
returned: always
type: complex
contains:
check_interval_sec:
checkIntervalSec:
description:
- How often (in seconds) to send a health check. The default value is 5 seconds.
returned: success
type: int
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -82,7 +82,7 @@ items:
the resource.
returned: success
type: str
healthy_threshold:
healthyThreshold:
description:
- A so-far unhealthy instance will be marked healthy after this many consecutive successes.
The default value is 2.
@ -103,14 +103,14 @@ items:
be a dash.
returned: success
type: str
timeout_sec:
timeoutSec:
description:
- How long (in seconds) to wait before claiming failure.
- The default value is 5 seconds. It is invalid for timeoutSec to have greater value
than checkIntervalSec.
returned: success
type: int
unhealthy_threshold:
unhealthyThreshold:
description:
- A so-far healthy instance will be marked unhealthy after this many consecutive failures.
The default value is 2.
@ -123,7 +123,7 @@ items:
be specified, which must match type field.
returned: success
type: str
http_health_check:
httpHealthCheck:
description:
- A nested object resource.
returned: success
@ -136,7 +136,7 @@ items:
is performed will be used.
returned: success
type: str
request_path:
requestPath:
description:
- The request path of the HTTP health check request.
- The default value is /.
@ -148,19 +148,19 @@ items:
- The default value is 80.
returned: success
type: int
port_name:
portName:
description:
- Port name as defined in InstanceGroup#NamedPort#name. If both port and port_name
are defined, port takes precedence.
returned: success
type: str
proxy_header:
proxyHeader:
description:
- Specifies the type of proxy header to append before sending data to the backend,
either NONE or PROXY_V1. The default is NONE.
returned: success
type: str
https_health_check:
httpsHealthCheck:
description:
- A nested object resource.
returned: success
@ -173,7 +173,7 @@ items:
is performed will be used.
returned: success
type: str
request_path:
requestPath:
description:
- The request path of the HTTPS health check request.
- The default value is /.
@ -185,19 +185,19 @@ items:
- The default value is 443.
returned: success
type: int
port_name:
portName:
description:
- Port name as defined in InstanceGroup#NamedPort#name. If both port and port_name
are defined, port takes precedence.
returned: success
type: str
proxy_header:
proxyHeader:
description:
- Specifies the type of proxy header to append before sending data to the backend,
either NONE or PROXY_V1. The default is NONE.
returned: success
type: str
tcp_health_check:
tcpHealthCheck:
description:
- A nested object resource.
returned: success
@ -223,19 +223,19 @@ items:
- The default value is 443.
returned: success
type: int
port_name:
portName:
description:
- Port name as defined in InstanceGroup#NamedPort#name. If both port and port_name
are defined, port takes precedence.
returned: success
type: str
proxy_header:
proxyHeader:
description:
- Specifies the type of proxy header to append before sending data to the backend,
either NONE or PROXY_V1. The default is NONE.
returned: success
type: str
ssl_health_check:
sslHealthCheck:
description:
- A nested object resource.
returned: success
@ -261,13 +261,13 @@ items:
- The default value is 443.
returned: success
type: int
port_name:
portName:
description:
- Port name as defined in InstanceGroup#NamedPort#name. If both port and port_name
are defined, port takes precedence.
returned: success
type: str
proxy_header:
proxyHeader:
description:
- Specifies the type of proxy header to append before sending data to the backend,
either NONE or PROXY_V1. The default is NONE.
@ -289,7 +289,7 @@ import json
def main():
module = GcpModule(
argument_spec=dict(
filters=dict(type='list', elements='str'),
filters=dict(type='list', elements='str')
)
)

@ -115,18 +115,18 @@ EXAMPLES = '''
timeout_sec: 2
unhealthy_threshold: 5
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
check_interval_sec:
checkIntervalSec:
description:
- How often (in seconds) to send a health check. The default value is 5 seconds.
returned: success
type: int
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -137,7 +137,7 @@ RETURN = '''
the resource.
returned: success
type: str
healthy_threshold:
healthyThreshold:
description:
- A so-far unhealthy instance will be marked healthy after this many consecutive successes.
The default value is 2.
@ -171,20 +171,20 @@ RETURN = '''
- The default value is 80.
returned: success
type: int
request_path:
requestPath:
description:
- The request path of the HTTP health check request.
- The default value is /.
returned: success
type: str
timeout_sec:
timeoutSec:
description:
- How long (in seconds) to wait before claiming failure.
- The default value is 5 seconds. It is invalid for timeoutSec to have greater value
than checkIntervalSec.
returned: success
type: int
unhealthy_threshold:
unhealthyThreshold:
description:
- A so-far healthy instance will be marked unhealthy after this many consecutive failures.
The default value is 2.
@ -235,7 +235,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -289,9 +290,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -302,9 +303,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/global/httpHealthChecks".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -319,8 +320,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result

@ -56,7 +56,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -66,12 +66,12 @@ items:
returned: always
type: complex
contains:
check_interval_sec:
checkIntervalSec:
description:
- How often (in seconds) to send a health check. The default value is 5 seconds.
returned: success
type: int
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -82,7 +82,7 @@ items:
the resource.
returned: success
type: str
healthy_threshold:
healthyThreshold:
description:
- A so-far unhealthy instance will be marked healthy after this many consecutive successes.
The default value is 2.
@ -116,20 +116,20 @@ items:
- The default value is 80.
returned: success
type: int
request_path:
requestPath:
description:
- The request path of the HTTP health check request.
- The default value is /.
returned: success
type: str
timeout_sec:
timeoutSec:
description:
- How long (in seconds) to wait before claiming failure.
- The default value is 5 seconds. It is invalid for timeoutSec to have greater value
than checkIntervalSec.
returned: success
type: int
unhealthy_threshold:
unhealthyThreshold:
description:
- A so-far healthy instance will be marked unhealthy after this many consecutive failures.
The default value is 2.
@ -151,7 +151,7 @@ import json
def main():
module = GcpModule(
argument_spec=dict(
filters=dict(type='list', elements='str'),
filters=dict(type='list', elements='str')
)
)

@ -113,18 +113,18 @@ EXAMPLES = '''
timeout_sec: 2
unhealthy_threshold: 5
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
check_interval_sec:
checkIntervalSec:
description:
- How often (in seconds) to send a health check. The default value is 5 seconds.
returned: success
type: int
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -135,7 +135,7 @@ RETURN = '''
the resource.
returned: success
type: str
healthy_threshold:
healthyThreshold:
description:
- A so-far unhealthy instance will be marked healthy after this many consecutive successes.
The default value is 2.
@ -169,20 +169,20 @@ RETURN = '''
- The default value is 80.
returned: success
type: int
request_path:
requestPath:
description:
- The request path of the HTTPS health check request.
- The default value is /.
returned: success
type: str
timeout_sec:
timeoutSec:
description:
- How long (in seconds) to wait before claiming failure.
- The default value is 5 seconds. It is invalid for timeoutSec to have greater value
than checkIntervalSec.
returned: success
type: int
unhealthy_threshold:
unhealthyThreshold:
description:
- A so-far healthy instance will be marked unhealthy after this many consecutive failures.
The default value is 2.
@ -233,7 +233,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -287,9 +288,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -300,9 +301,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/global/httpsHealthChecks".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -317,8 +318,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result

@ -56,7 +56,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -66,12 +66,12 @@ items:
returned: always
type: complex
contains:
check_interval_sec:
checkIntervalSec:
description:
- How often (in seconds) to send a health check. The default value is 5 seconds.
returned: success
type: int
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -82,7 +82,7 @@ items:
the resource.
returned: success
type: str
healthy_threshold:
healthyThreshold:
description:
- A so-far unhealthy instance will be marked healthy after this many consecutive successes.
The default value is 2.
@ -116,20 +116,20 @@ items:
- The default value is 80.
returned: success
type: int
request_path:
requestPath:
description:
- The request path of the HTTPS health check request.
- The default value is /.
returned: success
type: str
timeout_sec:
timeoutSec:
description:
- How long (in seconds) to wait before claiming failure.
- The default value is 5 seconds. It is invalid for timeoutSec to have greater value
than checkIntervalSec.
returned: success
type: int
unhealthy_threshold:
unhealthyThreshold:
description:
- A so-far healthy instance will be marked unhealthy after this many consecutive failures.
The default value is 2.
@ -151,7 +151,7 @@ import json
def main():
module = GcpModule(
argument_spec=dict(
filters=dict(type='list', elements='str'),
filters=dict(type='list', elements='str')
)
)

@ -148,6 +148,11 @@ options:
description:
- Refers to a gcompute_disk object You must provide either this property or the rawDisk.source
property but not both to create an image.
- 'This field represents a link to a Disk resource in GCP. It can be specified in
two ways. You can add `register: name-of-resource` to a gcp_compute_disk task and
then set this source_disk field to "{{ name-of-resource }}" Alternatively, you can
set this source_disk to a dictionary with the selfLink key where the value is the
selfLink of your Disk.'
required: false
source_disk_encryption_key:
description:
@ -196,18 +201,18 @@ EXAMPLES = '''
name: "test_object"
source_disk: "{{ disk }}"
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
archive_size_bytes:
archiveSizeBytes:
description:
- Size of the image tar.gz archive stored in Google Cloud Storage (in bytes).
returned: success
type: int
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -261,7 +266,7 @@ RETURN = '''
the resource.
returned: success
type: str
disk_size_gb:
diskSizeGb:
description:
- Size of the image when restored onto a persistent disk (in GB).
returned: success
@ -274,7 +279,7 @@ RETURN = '''
comply with RFC1035.
returned: success
type: str
guest_os_features:
guestOsFeatures:
description:
- A list of features to enable on the guest OS. Applicable for bootable images only.
Currently, only one feature can be enabled, VIRTIO_SCSI_MULTIQUEUE, which allows
@ -300,7 +305,7 @@ RETURN = '''
- The unique identifier for the resource. This identifier is defined by the server.
returned: success
type: int
image_encryption_key:
imageEncryptionKey:
description:
- Encrypts the image using a customer-supplied encryption key.
- After you encrypt an image with a customer-supplied key, you must provide the same
@ -308,7 +313,7 @@ RETURN = '''
returned: success
type: complex
contains:
raw_key:
rawKey:
description:
- Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64
to either encrypt or decrypt this resource.
@ -335,20 +340,20 @@ RETURN = '''
be a dash.
returned: success
type: str
raw_disk:
rawDisk:
description:
- The parameters of the raw disk image.
returned: success
type: complex
contains:
container_type:
containerType:
description:
- The format used to encode and transmit the block device, which should be TAR. This
is just a container and transmission format and not a runtime format. Provided by
the client when the disk image is created.
returned: success
type: str
sha1_checksum:
sha1Checksum:
description:
- An optional SHA1 checksum of the disk image before unpackaging.
- This is provided by the client when the disk image is created.
@ -360,20 +365,20 @@ RETURN = '''
either this property or the sourceDisk property but not both.
returned: success
type: str
source_disk:
sourceDisk:
description:
- Refers to a gcompute_disk object You must provide either this property or the rawDisk.source
property but not both to create an image.
returned: success
type: dict
source_disk_encryption_key:
sourceDiskEncryptionKey:
description:
- The customer-supplied encryption key of the source disk. Required if the source
disk is protected by a customer-supplied encryption key.
returned: success
type: complex
contains:
raw_key:
rawKey:
description:
- Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64
to either encrypt or decrypt this resource.
@ -385,14 +390,14 @@ RETURN = '''
that protects this resource.
returned: success
type: str
source_disk_id:
sourceDiskId:
description:
- The ID value of the disk used to create this image. This value may be used to determine
whether the image was taken from the current or a previous instance of a given disk
name.
returned: success
type: str
source_type:
sourceType:
description:
- The type of the image used to create this disk. The default and only value is RAW
.
@ -458,7 +463,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -515,9 +521,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -528,9 +534,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/global/images".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -545,8 +551,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result

@ -56,7 +56,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -66,12 +66,12 @@ items:
returned: always
type: complex
contains:
archive_size_bytes:
archiveSizeBytes:
description:
- Size of the image tar.gz archive stored in Google Cloud Storage (in bytes).
returned: success
type: int
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -125,7 +125,7 @@ items:
the resource.
returned: success
type: str
disk_size_gb:
diskSizeGb:
description:
- Size of the image when restored onto a persistent disk (in GB).
returned: success
@ -138,7 +138,7 @@ items:
comply with RFC1035.
returned: success
type: str
guest_os_features:
guestOsFeatures:
description:
- A list of features to enable on the guest OS. Applicable for bootable images only.
Currently, only one feature can be enabled, VIRTIO_SCSI_MULTIQUEUE, which allows
@ -164,7 +164,7 @@ items:
- The unique identifier for the resource. This identifier is defined by the server.
returned: success
type: int
image_encryption_key:
imageEncryptionKey:
description:
- Encrypts the image using a customer-supplied encryption key.
- After you encrypt an image with a customer-supplied key, you must provide the same
@ -172,7 +172,7 @@ items:
returned: success
type: complex
contains:
raw_key:
rawKey:
description:
- Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64
to either encrypt or decrypt this resource.
@ -199,20 +199,20 @@ items:
be a dash.
returned: success
type: str
raw_disk:
rawDisk:
description:
- The parameters of the raw disk image.
returned: success
type: complex
contains:
container_type:
containerType:
description:
- The format used to encode and transmit the block device, which should be TAR. This
is just a container and transmission format and not a runtime format. Provided by
the client when the disk image is created.
returned: success
type: str
sha1_checksum:
sha1Checksum:
description:
- An optional SHA1 checksum of the disk image before unpackaging.
- This is provided by the client when the disk image is created.
@ -224,20 +224,20 @@ items:
either this property or the sourceDisk property but not both.
returned: success
type: str
source_disk:
sourceDisk:
description:
- Refers to a gcompute_disk object You must provide either this property or the rawDisk.source
property but not both to create an image.
returned: success
type: dict
source_disk_encryption_key:
sourceDiskEncryptionKey:
description:
- The customer-supplied encryption key of the source disk. Required if the source
disk is protected by a customer-supplied encryption key.
returned: success
type: complex
contains:
raw_key:
rawKey:
description:
- Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64
to either encrypt or decrypt this resource.
@ -249,14 +249,14 @@ items:
that protects this resource.
returned: success
type: str
source_disk_id:
sourceDiskId:
description:
- The ID value of the disk used to create this image. This value may be used to determine
whether the image was taken from the current or a previous instance of a given disk
name.
returned: success
type: str
source_type:
sourceType:
description:
- The type of the image used to create this disk. The default and only value is RAW
.
@ -278,7 +278,7 @@ import json
def main():
module = GcpModule(
argument_spec=dict(
filters=dict(type='list', elements='str'),
filters=dict(type='list', elements='str')
)
)

@ -171,6 +171,11 @@ options:
or disks.source is required.
- If desired, you can also attach existing non-root persistent disks using this property.
This field is only applicable for persistent disks.
- 'This field represents a link to a Disk resource in GCP. It can be specified in
two ways. You can add `register: name-of-resource` to a gcp_compute_disk task and
then set this source field to "{{ name-of-resource }}" Alternatively, you can set
this source to a dictionary with the selfLink key where the value is the selfLink
of your Disk.'
required: false
type:
description:
@ -249,6 +254,11 @@ options:
field undefined to use an IP from a shared ephemeral IP address pool. If you specify
a static external IP address, it must live in the same region as the zone of the
instance.
- 'This field represents a link to a Address resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_address task
and then set this nat_ip field to "{{ name-of-resource }}" Alternatively, you can
set this nat_ip to a dictionary with the address key where the value is the address
of your Address.'
required: false
type:
description:
@ -286,6 +296,11 @@ options:
if neither the network nor the subnetwork is specified, the default network global/networks/default
is used; if the network is not specified but the subnetwork is specified, the network
is inferred.
- 'This field represents a link to a Network resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_network task
and then set this network field to "{{ name-of-resource }}" Alternatively, you can
set this network to a dictionary with the selfLink key where the value is the selfLink
of your Network.'
required: false
network_ip:
description:
@ -298,6 +313,11 @@ options:
- If the network resource is in legacy mode, do not provide this property. If the
network is in auto subnet mode, providing the subnetwork is optional. If the network
is in custom subnet mode, then this field should be specified.
- 'This field represents a link to a Subnetwork resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_subnetwork
task and then set this subnetwork field to "{{ name-of-resource }}" Alternatively,
you can set this subnetwork to a dictionary with the selfLink key where the value
is the selfLink of your Subnetwork.'
required: false
scheduling:
description:
@ -417,24 +437,24 @@ EXAMPLES = '''
type: ONE_TO_ONE_NAT
zone: us-central1-a
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
can_ip_forward:
canIpForward:
description:
- Allows this instance to send and receive packets with non-matching destination or
source IPs. This is required if you plan to use this instance to forward routes.
returned: success
type: bool
cpu_platform:
cpuPlatform:
description:
- The CPU platform used by this instance.
returned: success
type: str
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -446,7 +466,7 @@ RETURN = '''
returned: success
type: complex
contains:
auto_delete:
autoDelete:
description:
- Specifies whether the disk will be auto-deleted when the instance is deleted (but
not when the disk is detached from the instance).
@ -460,26 +480,26 @@ RETURN = '''
of the disk for its root filesystem.
returned: success
type: bool
device_name:
deviceName:
description:
- Specifies a unique device name of your choice that is reflected into the /dev/disk/by-id/google-*
tree of a Linux operating system running within the instance. This name can be used
to reference the device for mounting, resizing, and so on, from within the instance.
returned: success
type: str
disk_encryption_key:
diskEncryptionKey:
description:
- Encrypts or decrypts a disk using a customer-supplied encryption key.
returned: success
type: complex
contains:
raw_key:
rawKey:
description:
- Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64
to either encrypt or decrypt this resource.
returned: success
type: str
rsa_encrypted_key:
rsaEncryptedKey:
description:
- Specifies an RFC 4648 base64 encoded, RSA-wrapped 2048-bit customer-supplied encryption
key to either encrypt or decrypt this resource.
@ -498,7 +518,7 @@ RETURN = '''
a unique index number. If not specified, the server will choose an appropriate value.
returned: success
type: int
initialize_params:
initializeParams:
description:
- Specifies the parameters for a new disk that will be created alongside the new instance.
Use initialization parameters to create boot disks or local SSDs attached to the
@ -506,32 +526,32 @@ RETURN = '''
returned: success
type: complex
contains:
disk_name:
diskName:
description:
- Specifies the disk name. If not specified, the default is to use the name of the
instance.
returned: success
type: str
disk_size_gb:
diskSizeGb:
description:
- Specifies the size of the disk in base-2 GB.
returned: success
type: int
disk_type:
diskType:
description:
- Reference to a gcompute_disk_type resource.
- Specifies the disk type to use to create the instance.
- If not specified, the default is pd-standard.
returned: success
type: str
source_image:
sourceImage:
description:
- The source image to create this disk. When creating a new instance, one of initializeParams.sourceImage
or disks.source is required. To create a disk with one of the public operating
system images, specify the image by its family name.
returned: success
type: str
source_image_encryption_key:
sourceImageEncryptionKey:
description:
- The customer-supplied encryption key of the source image. Required if the source
image is protected by a customer-supplied encryption key.
@ -541,7 +561,7 @@ RETURN = '''
returned: success
type: complex
contains:
raw_key:
rawKey:
description:
- Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64
to either encrypt or decrypt this resource.
@ -581,18 +601,18 @@ RETURN = '''
the default is PERSISTENT.
returned: success
type: str
guest_accelerators:
guestAccelerators:
description:
- List of the type and count of accelerator cards attached to the instance .
returned: success
type: complex
contains:
accelerator_count:
acceleratorCount:
description:
- The number of the guest accelerator cards exposed to this instance.
returned: success
type: int
accelerator_type:
acceleratorType:
description:
- Full or partial URL of the accelerator type resource to expose to this instance.
returned: success
@ -602,7 +622,7 @@ RETURN = '''
- The unique identifier for the resource. This identifier is defined by the server.
returned: success
type: int
label_fingerprint:
labelFingerprint:
description:
- A fingerprint for this request, which is essentially a hash of the metadata's contents
and used for optimistic locking. The fingerprint is initially generated by Compute
@ -616,12 +636,12 @@ RETURN = '''
These pairs can consist of custom metadata or predefined keys.
returned: success
type: dict
machine_type:
machineType:
description:
- A reference to a machine type which defines VM kind.
returned: success
type: str
min_cpu_platform:
minCpuPlatform:
description:
- Specifies a minimum CPU platform for the VM instance. Applicable values are the
friendly names of CPU platforms .
@ -637,7 +657,7 @@ RETURN = '''
be a dash.
returned: success
type: str
network_interfaces:
networkInterfaces:
description:
- An array of configurations for this interface. This specifies how this interface
is configured to interact with other network services, such as connecting to the
@ -645,7 +665,7 @@ RETURN = '''
returned: success
type: complex
contains:
access_configs:
accessConfigs:
description:
- An array of configurations for this interface. Currently, only one access config,
ONE_TO_ONE_NAT, is supported. If there are no accessConfigs specified, then this
@ -660,7 +680,7 @@ RETURN = '''
IP or Network Access.
returned: success
type: str
nat_ip:
natIP:
description:
- Specifies the title of a gcompute_address.
- An external IP address associated with this instance.
@ -675,14 +695,14 @@ RETURN = '''
- The type of configuration. The default and only option is ONE_TO_ONE_NAT.
returned: success
type: str
alias_ip_ranges:
aliasIpRanges:
description:
- An array of alias IP ranges for this network interface. Can only be specified for
network interfaces on subnet-mode networks.
returned: success
type: complex
contains:
ip_cidr_range:
ipCidrRange:
description:
- The IP CIDR range represented by this alias IP range.
- This IP CIDR range must belong to the specified subnetwork and cannot contain IP
@ -691,7 +711,7 @@ RETURN = '''
(e.g. 10.1.2.0/24).
returned: success
type: str
subnetwork_range_name:
subnetworkRangeName:
description:
- Optional subnetwork secondary range name specifying the secondary range from which
to allocate the IP CIDR range for this alias IP range. If left unspecified, the
@ -712,7 +732,7 @@ RETURN = '''
is inferred.
returned: success
type: dict
network_ip:
networkIP:
description:
- An IPv4 internal network address to assign to the instance for this network interface.
If not specified by the user, an unused internal IP is assigned by the system.
@ -732,7 +752,7 @@ RETURN = '''
returned: success
type: complex
contains:
automatic_restart:
automaticRestart:
description:
- Specifies whether the instance should be automatically restarted if it is terminated
by Compute Engine (not terminated by a user).
@ -740,7 +760,7 @@ RETURN = '''
instances cannot be automatically restarted.
returned: success
type: bool
on_host_maintenance:
onHostMaintenance:
description:
- Defines the maintenance behavior for this instance. For standard instances, the
default behavior is MIGRATE. For preemptible instances, the default and only possible
@ -754,7 +774,7 @@ RETURN = '''
creation, it cannot be set or changed after the instance has been created.
returned: success
type: bool
service_accounts:
serviceAccounts:
description:
- A list of service accounts, with their specified scopes, authorized for this instance.
Only one service account per VM instance is supported.
@ -777,7 +797,7 @@ RETURN = '''
RUNNING, STOPPING, SUSPENDING, SUSPENDED, and TERMINATED.'
returned: success
type: str
status_message:
statusMessage:
description:
- An optional, human-readable explanation of the status.
returned: success
@ -911,7 +931,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind, fetch)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -934,9 +955,28 @@ def create(module, link, kind):
return wait_for_operation(module, auth.post(link, resource_to_request(module)))
def update(module, link, kind):
def update(module, link, kind, fetch):
update_fields(module, resource_to_request(module),
response_to_hash(module, fetch))
return fetch_resource(module, self_link(module), kind)
def update_fields(module, request, response):
if response.get('machineType') != request.get('machineType'):
machine_type_update(module, request, response)
def machine_type_update(module, request, response):
auth = GcpSession(module, 'compute')
return wait_for_operation(module, auth.put(link, resource_to_request(module)))
auth.post(
''.join([
"https://www.googleapis.com/compute/v1/",
"projdcts/{project}/zones/{zone}/instances/{name}/setMachineType"
]).format(**module.params),
{
u'machineType': machine_type_selflink(module.params.get('machine_type'), module.params)
}
)
def delete(module, link, kind):
@ -969,9 +1009,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -982,9 +1022,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/instances".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -1001,8 +1041,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result
@ -1053,7 +1091,7 @@ def response_to_hash(module, response):
def disk_type_selflink(name, params):
if name is None:
return
url = r"https://www.googleapis.com/compute/v1/projects/.*/zones/{zone}/diskTypes/[a-z1-9\-]*"
url = r"https://www.googleapis.com/compute/v1/projects/.*/zones/[a-z1-9\-]*/diskTypes/[a-z1-9\-]*"
if not re.match(url, name):
name = "https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/diskTypes/%s".format(**params) % name
return name
@ -1062,7 +1100,7 @@ def disk_type_selflink(name, params):
def machine_type_selflink(name, params):
if name is None:
return
url = r"https://www.googleapis.com/compute/v1/projects/.*/zones/{zone}/machineTypes/[a-z1-9\-]*"
url = r"https://www.googleapis.com/compute/v1/projects/.*/zones/[a-z1-9\-]*/machineTypes/[a-z1-9\-]*"
if not re.match(url, name):
name = "https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/machineTypes/%s".format(**params) % name
return name
@ -1112,7 +1150,7 @@ def encode_request(request, module):
def decode_response(response, module):
if 'metadata' in response:
if 'metadata' in response and response['metadata'] is not None:
response['metadata'] = metadata_decoder(response['metadata'])
return response

@ -61,7 +61,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -71,18 +71,18 @@ items:
returned: always
type: complex
contains:
can_ip_forward:
canIpForward:
description:
- Allows this instance to send and receive packets with non-matching destination or
source IPs. This is required if you plan to use this instance to forward routes.
returned: success
type: bool
cpu_platform:
cpuPlatform:
description:
- The CPU platform used by this instance.
returned: success
type: str
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -94,7 +94,7 @@ items:
returned: success
type: complex
contains:
auto_delete:
autoDelete:
description:
- Specifies whether the disk will be auto-deleted when the instance is deleted (but
not when the disk is detached from the instance).
@ -108,26 +108,26 @@ items:
of the disk for its root filesystem.
returned: success
type: bool
device_name:
deviceName:
description:
- Specifies a unique device name of your choice that is reflected into the /dev/disk/by-id/google-*
tree of a Linux operating system running within the instance. This name can be used
to reference the device for mounting, resizing, and so on, from within the instance.
returned: success
type: str
disk_encryption_key:
diskEncryptionKey:
description:
- Encrypts or decrypts a disk using a customer-supplied encryption key.
returned: success
type: complex
contains:
raw_key:
rawKey:
description:
- Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64
to either encrypt or decrypt this resource.
returned: success
type: str
rsa_encrypted_key:
rsaEncryptedKey:
description:
- Specifies an RFC 4648 base64 encoded, RSA-wrapped 2048-bit customer-supplied encryption
key to either encrypt or decrypt this resource.
@ -146,7 +146,7 @@ items:
a unique index number. If not specified, the server will choose an appropriate value.
returned: success
type: int
initialize_params:
initializeParams:
description:
- Specifies the parameters for a new disk that will be created alongside the new instance.
Use initialization parameters to create boot disks or local SSDs attached to the
@ -154,32 +154,32 @@ items:
returned: success
type: complex
contains:
disk_name:
diskName:
description:
- Specifies the disk name. If not specified, the default is to use the name of the
instance.
returned: success
type: str
disk_size_gb:
diskSizeGb:
description:
- Specifies the size of the disk in base-2 GB.
returned: success
type: int
disk_type:
diskType:
description:
- Reference to a gcompute_disk_type resource.
- Specifies the disk type to use to create the instance.
- If not specified, the default is pd-standard.
returned: success
type: str
source_image:
sourceImage:
description:
- The source image to create this disk. When creating a new instance, one of initializeParams.sourceImage
or disks.source is required. To create a disk with one of the public operating
system images, specify the image by its family name.
returned: success
type: str
source_image_encryption_key:
sourceImageEncryptionKey:
description:
- The customer-supplied encryption key of the source image. Required if the source
image is protected by a customer-supplied encryption key.
@ -189,7 +189,7 @@ items:
returned: success
type: complex
contains:
raw_key:
rawKey:
description:
- Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64
to either encrypt or decrypt this resource.
@ -229,18 +229,18 @@ items:
the default is PERSISTENT.
returned: success
type: str
guest_accelerators:
guestAccelerators:
description:
- List of the type and count of accelerator cards attached to the instance .
returned: success
type: complex
contains:
accelerator_count:
acceleratorCount:
description:
- The number of the guest accelerator cards exposed to this instance.
returned: success
type: int
accelerator_type:
acceleratorType:
description:
- Full or partial URL of the accelerator type resource to expose to this instance.
returned: success
@ -250,7 +250,7 @@ items:
- The unique identifier for the resource. This identifier is defined by the server.
returned: success
type: int
label_fingerprint:
labelFingerprint:
description:
- A fingerprint for this request, which is essentially a hash of the metadata's contents
and used for optimistic locking. The fingerprint is initially generated by Compute
@ -264,12 +264,12 @@ items:
These pairs can consist of custom metadata or predefined keys.
returned: success
type: dict
machine_type:
machineType:
description:
- A reference to a machine type which defines VM kind.
returned: success
type: str
min_cpu_platform:
minCpuPlatform:
description:
- Specifies a minimum CPU platform for the VM instance. Applicable values are the
friendly names of CPU platforms .
@ -285,7 +285,7 @@ items:
be a dash.
returned: success
type: str
network_interfaces:
networkInterfaces:
description:
- An array of configurations for this interface. This specifies how this interface
is configured to interact with other network services, such as connecting to the
@ -293,7 +293,7 @@ items:
returned: success
type: complex
contains:
access_configs:
accessConfigs:
description:
- An array of configurations for this interface. Currently, only one access config,
ONE_TO_ONE_NAT, is supported. If there are no accessConfigs specified, then this
@ -308,7 +308,7 @@ items:
IP or Network Access.
returned: success
type: str
nat_ip:
natIP:
description:
- Specifies the title of a gcompute_address.
- An external IP address associated with this instance.
@ -323,14 +323,14 @@ items:
- The type of configuration. The default and only option is ONE_TO_ONE_NAT.
returned: success
type: str
alias_ip_ranges:
aliasIpRanges:
description:
- An array of alias IP ranges for this network interface. Can only be specified for
network interfaces on subnet-mode networks.
returned: success
type: complex
contains:
ip_cidr_range:
ipCidrRange:
description:
- The IP CIDR range represented by this alias IP range.
- This IP CIDR range must belong to the specified subnetwork and cannot contain IP
@ -339,7 +339,7 @@ items:
(e.g. 10.1.2.0/24).
returned: success
type: str
subnetwork_range_name:
subnetworkRangeName:
description:
- Optional subnetwork secondary range name specifying the secondary range from which
to allocate the IP CIDR range for this alias IP range. If left unspecified, the
@ -360,7 +360,7 @@ items:
is inferred.
returned: success
type: dict
network_ip:
networkIP:
description:
- An IPv4 internal network address to assign to the instance for this network interface.
If not specified by the user, an unused internal IP is assigned by the system.
@ -380,7 +380,7 @@ items:
returned: success
type: complex
contains:
automatic_restart:
automaticRestart:
description:
- Specifies whether the instance should be automatically restarted if it is terminated
by Compute Engine (not terminated by a user).
@ -388,7 +388,7 @@ items:
instances cannot be automatically restarted.
returned: success
type: bool
on_host_maintenance:
onHostMaintenance:
description:
- Defines the maintenance behavior for this instance. For standard instances, the
default behavior is MIGRATE. For preemptible instances, the default and only possible
@ -402,7 +402,7 @@ items:
creation, it cannot be set or changed after the instance has been created.
returned: success
type: bool
service_accounts:
serviceAccounts:
description:
- A list of service accounts, with their specified scopes, authorized for this instance.
Only one service account per VM instance is supported.
@ -425,7 +425,7 @@ items:
RUNNING, STOPPING, SUSPENDING, SUSPENDED, and TERMINATED.'
returned: success
type: str
status_message:
statusMessage:
description:
- An optional, human-readable explanation of the status.
returned: success

@ -81,6 +81,11 @@ options:
network:
description:
- The network to which all instances in the instance group belong.
- 'This field represents a link to a Network resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_network task
and then set this network field to "{{ name-of-resource }}" Alternatively, you can
set this network to a dictionary with the selfLink key where the value is the selfLink
of your Network.'
required: false
region:
description:
@ -89,11 +94,25 @@ options:
subnetwork:
description:
- The subnetwork to which all instances in the instance group belong.
- 'This field represents a link to a Subnetwork resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_subnetwork
task and then set this subnetwork field to "{{ name-of-resource }}" Alternatively,
you can set this subnetwork to a dictionary with the selfLink key where the value
is the selfLink of your Subnetwork.'
required: false
zone:
description:
- A reference to the zone where the instance group resides.
required: true
instances:
description:
- The list of instances associated with this InstanceGroup.
- All instances must be created before being added to an InstanceGroup.
- All instances not in this list will be removed from the InstanceGroup and will not
be deleted.
- Only the full identifier of the instance will be returned.
required: false
version_added: 2.8
extends_documentation_fragment: gcp
'''
@ -116,13 +135,13 @@ EXAMPLES = '''
network: "{{ network }}"
zone: us-central1-a
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -144,7 +163,7 @@ RETURN = '''
- The name must be 1-63 characters long, and comply with RFC1035.
returned: success
type: str
named_ports:
namedPorts:
description:
- Assigns a name to a port number.
- 'For example: {name: "http", port: 80}.'
@ -186,6 +205,15 @@ RETURN = '''
- A reference to the zone where the instance group resides.
returned: success
type: str
instances:
description:
- The list of instances associated with this InstanceGroup.
- All instances must be created before being added to an InstanceGroup.
- All instances not in this list will be removed from the InstanceGroup and will not
be deleted.
- Only the full identifier of the instance will be returned.
returned: success
type: list
'''
################################################################################
@ -217,7 +245,8 @@ def main():
network=dict(type='dict'),
region=dict(type='str'),
subnetwork=dict(type='dict'),
zone=dict(required=True, type='str')
zone=dict(required=True, type='str'),
instances=dict(type='list', elements='dict')
)
)
@ -233,7 +262,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -246,6 +276,10 @@ def main():
else:
fetch = {}
if fetch:
instance = InstanceLogic(module)
instance.run()
fetch.update({'instances': instance.list_instances()})
fetch.update({'changed': changed})
module.exit_json(**fetch)
@ -257,7 +291,8 @@ def create(module, link, kind):
def update(module, link, kind):
module.fail_json(msg="InstanceGroup cannot be edited")
instance = InstanceLogic(module)
instance.run()
def delete(module, link, kind):
@ -283,9 +318,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -296,9 +331,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/instanceGroups".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -313,8 +348,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result
@ -398,6 +431,66 @@ def raise_if_errors(response, err_path, module):
module.fail_json(msg=errors)
class InstanceLogic(object):
def __init__(self, module):
self.module = module
self.current_instances = self.list_instances()
self.module_instances = []
# Transform module list of instances (dicts of instance responses) into a list of selfLinks.
instances = self.module.params.get('instances')
if instances:
for instance in instances:
self.module_instances.append(replace_resource_dict(instance, 'selfLink'))
def run(self):
# Find all instances to add and add them
instances_to_add = list(set(self.module_instances) - set(self.current_instances))
if instances_to_add:
self.add_instances(instances_to_add)
# Find all instances to remove and remove them
instances_to_remove = list(set(self.current_instances) - set(self.module_instances))
if instances_to_remove:
self.remove_instances(instances_to_remove)
def list_instances(self):
auth = GcpSession(self.module, 'compute')
response = return_if_object(self.module, auth.post(self._list_instances_url(), {'instanceState': 'ALL'}),
'compute#instanceGroupsListInstances')
# Transform instance list into a list of selfLinks for diffing with module parameters
instances = []
for instance in response.get('items', []):
instances.append(instance['instance'])
return instances
def add_instances(self, instances):
auth = GcpSession(self.module, 'compute')
wait_for_operation(self.module, auth.post(self._add_instances_url(), self._build_request(instances)))
def remove_instances(self, instances):
auth = GcpSession(self.module, 'compute')
wait_for_operation(self.module, auth.post(self._remove_instances_url(), self._build_request(instances)))
def _list_instances_url(self):
return "https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/instanceGroups/{name}/listInstances".format(**self.module.params)
def _remove_instances_url(self):
return "https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/instanceGroups/{name}/removeInstances".format(**self.module.params)
def _add_instances_url(self):
return "https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/instanceGroups/{name}/addInstances".format(**self.module.params)
def _build_request(self, instances):
request = {
'instances': []
}
for instance in instances:
request['instances'].append({'instance': instance})
return request
class InstanceGroupNamedPortsArray(object):
def __init__(self, request, module):
self.module = module

@ -61,7 +61,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -71,7 +71,7 @@ items:
returned: always
type: complex
contains:
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -93,7 +93,7 @@ items:
- The name must be 1-63 characters long, and comply with RFC1035.
returned: success
type: str
named_ports:
namedPorts:
description:
- Assigns a name to a port number.
- 'For example: {name: "http", port: 80}.'
@ -135,6 +135,15 @@ items:
- A reference to the zone where the instance group resides.
returned: success
type: str
instances:
description:
- The list of instances associated with this InstanceGroup.
- All instances must be created before being added to an InstanceGroup.
- All instances not in this list will be removed from the InstanceGroup and will not
be deleted.
- Only the full identifier of the instance will be returned.
returned: success
type: list
'''
################################################################################

@ -67,6 +67,11 @@ options:
description:
- The instance template that is specified for this managed instance group. The group
uses this template to create all new instances in the managed instance group.
- 'This field represents a link to a InstanceTemplate resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_instance_template
task and then set this instance_template field to "{{ name-of-resource }}" Alternatively,
you can set this instance_template to a dictionary with the selfLink key where the
value is the selfLink of your InstanceTemplate.'
required: true
name:
description:
@ -156,13 +161,13 @@ EXAMPLES = '''
target_size: 3
zone: us-west1-a
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
base_instance_name:
baseInstanceName:
description:
- The base instance name to use for instances in this group. The value must be 1-58
characters long. Instances are named by appending a hyphen and a random four-character
@ -170,12 +175,12 @@ RETURN = '''
- The base instance name must comply with RFC1035.
returned: success
type: str
creation_timestamp:
creationTimestamp:
description:
- The creation timestamp for this managed instance group in RFC3339 text format.
returned: success
type: str
current_actions:
currentActions:
description:
- The list of instance actions and the number of instances in this managed instance
group that are scheduled for each of those actions.
@ -198,7 +203,7 @@ RETURN = '''
the creatingWithoutRetries field will be populated.
returned: success
type: int
creating_without_retries:
creatingWithoutRetries:
description:
- The number of instances that the managed instance group will attempt to create.
The group attempts to create each instance only once. If the group fails to create
@ -249,12 +254,12 @@ RETURN = '''
- A unique identifier for this resource.
returned: success
type: int
instance_group:
instanceGroup:
description:
- The instance group being managed.
returned: success
type: dict
instance_template:
instanceTemplate:
description:
- The instance template that is specified for this managed instance group. The group
uses this template to create all new instances in the managed instance group.
@ -266,7 +271,7 @@ RETURN = '''
comply with RFC1035.
returned: success
type: str
named_ports:
namedPorts:
description:
- Named ports configured for the Instance Groups complementary to this Instance Group
Manager.
@ -289,14 +294,14 @@ RETURN = '''
- The region this managed instance group resides (for regional resources).
returned: success
type: str
target_pools:
targetPools:
description:
- TargetPool resources to which instances in the instanceGroup field are added. The
target pools automatically apply to all of the instances in the managed instance
group.
returned: success
type: list
target_size:
targetSize:
description:
- The target number of running instances for this managed instance group. Deleting
or abandoning instances reduces this number. Resizing the group changes this number.
@ -355,7 +360,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -407,9 +413,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -420,9 +426,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/instanceGroupManagers".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -437,8 +443,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result

@ -61,7 +61,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -71,7 +71,7 @@ items:
returned: always
type: complex
contains:
base_instance_name:
baseInstanceName:
description:
- The base instance name to use for instances in this group. The value must be 1-58
characters long. Instances are named by appending a hyphen and a random four-character
@ -79,12 +79,12 @@ items:
- The base instance name must comply with RFC1035.
returned: success
type: str
creation_timestamp:
creationTimestamp:
description:
- The creation timestamp for this managed instance group in RFC3339 text format.
returned: success
type: str
current_actions:
currentActions:
description:
- The list of instance actions and the number of instances in this managed instance
group that are scheduled for each of those actions.
@ -107,7 +107,7 @@ items:
the creatingWithoutRetries field will be populated.
returned: success
type: int
creating_without_retries:
creatingWithoutRetries:
description:
- The number of instances that the managed instance group will attempt to create.
The group attempts to create each instance only once. If the group fails to create
@ -158,12 +158,12 @@ items:
- A unique identifier for this resource.
returned: success
type: int
instance_group:
instanceGroup:
description:
- The instance group being managed.
returned: success
type: dict
instance_template:
instanceTemplate:
description:
- The instance template that is specified for this managed instance group. The group
uses this template to create all new instances in the managed instance group.
@ -175,7 +175,7 @@ items:
comply with RFC1035.
returned: success
type: str
named_ports:
namedPorts:
description:
- Named ports configured for the Instance Groups complementary to this Instance Group
Manager.
@ -198,14 +198,14 @@ items:
- The region this managed instance group resides (for regional resources).
returned: success
type: str
target_pools:
targetPools:
description:
- TargetPool resources to which instances in the instanceGroup field are added. The
target pools automatically apply to all of the instances in the managed instance
group.
returned: success
type: list
target_size:
targetSize:
description:
- The target number of running instances for this managed instance group. Deleting
or abandoning instances reduces this number. Resizing the group changes this number.

@ -200,6 +200,11 @@ options:
- If desired, you can also attach existing non-root persistent disks using this property.
This field is only applicable for persistent disks.
- Note that for InstanceTemplate, specify the disk name, not the URL for the disk.
- 'This field represents a link to a Disk resource in GCP. It can be specified in
two ways. You can add `register: name-of-resource` to a gcp_compute_disk task and
then set this source field to "{{ name-of-resource }}" Alternatively, you can set
this source to a dictionary with the name key where the value is the name of your
Disk.'
required: false
type:
description:
@ -257,6 +262,11 @@ options:
field undefined to use an IP from a shared ephemeral IP address pool. If you specify
a static external IP address, it must live in the same region as the zone of the
instance.
- 'This field represents a link to a Address resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_address task
and then set this nat_ip field to "{{ name-of-resource }}" Alternatively, you can
set this nat_ip to a dictionary with the address key where the value is the address
of your Address.'
required: false
type:
description:
@ -294,6 +304,11 @@ options:
if neither the network nor the subnetwork is specified, the default network global/networks/default
is used; if the network is not specified but the subnetwork is specified, the network
is inferred.
- 'This field represents a link to a Network resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_network task
and then set this network field to "{{ name-of-resource }}" Alternatively, you can
set this network to a dictionary with the selfLink key where the value is the selfLink
of your Network.'
required: false
network_ip:
description:
@ -306,6 +321,11 @@ options:
- If the network resource is in legacy mode, do not provide this property. If the
network is in auto subnet mode, providing the subnetwork is optional. If the network
is in custom subnet mode, then this field should be specified.
- 'This field represents a link to a Subnetwork resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_subnetwork
task and then set this subnetwork field to "{{ name-of-resource }}" Alternatively,
you can set this subnetwork to a dictionary with the selfLink key where the value
is the selfLink of your Subnetwork.'
required: false
scheduling:
description:
@ -407,13 +427,13 @@ EXAMPLES = '''
type: ONE_TO_ONE_NAT
nat_ip: "{{ address }}"
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -440,7 +460,7 @@ RETURN = '''
returned: success
type: complex
contains:
can_ip_forward:
canIpForward:
description:
- Enables instances created based on this template to send packets with source IP
addresses other than their own and receive packets with destination IP addresses
@ -462,7 +482,7 @@ RETURN = '''
returned: success
type: complex
contains:
auto_delete:
autoDelete:
description:
- Specifies whether the disk will be auto-deleted when the instance is deleted (but
not when the disk is detached from the instance).
@ -476,26 +496,26 @@ RETURN = '''
of the disk for its root filesystem.
returned: success
type: bool
device_name:
deviceName:
description:
- Specifies a unique device name of your choice that is reflected into the /dev/disk/by-id/google-*
tree of a Linux operating system running within the instance. This name can be used
to reference the device for mounting, resizing, and so on, from within the instance.
returned: success
type: str
disk_encryption_key:
diskEncryptionKey:
description:
- Encrypts or decrypts a disk using a customer-supplied encryption key.
returned: success
type: complex
contains:
raw_key:
rawKey:
description:
- Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64
to either encrypt or decrypt this resource.
returned: success
type: str
rsa_encrypted_key:
rsaEncryptedKey:
description:
- Specifies an RFC 4648 base64 encoded, RSA-wrapped 2048-bit customer-supplied encryption
key to either encrypt or decrypt this resource.
@ -514,7 +534,7 @@ RETURN = '''
a unique index number. If not specified, the server will choose an appropriate value.
returned: success
type: int
initialize_params:
initializeParams:
description:
- Specifies the parameters for a new disk that will be created alongside the new instance.
Use initialization parameters to create boot disks or local SSDs attached to the
@ -522,32 +542,32 @@ RETURN = '''
returned: success
type: complex
contains:
disk_name:
diskName:
description:
- Specifies the disk name. If not specified, the default is to use the name of the
instance.
returned: success
type: str
disk_size_gb:
diskSizeGb:
description:
- Specifies the size of the disk in base-2 GB.
returned: success
type: int
disk_type:
diskType:
description:
- Reference to a gcompute_disk_type resource.
- Specifies the disk type to use to create the instance.
- If not specified, the default is pd-standard.
returned: success
type: str
source_image:
sourceImage:
description:
- The source image to create this disk. When creating a new instance, one of initializeParams.sourceImage
or disks.source is required. To create a disk with one of the public operating
system images, specify the image by its family name.
returned: success
type: str
source_image_encryption_key:
sourceImageEncryptionKey:
description:
- The customer-supplied encryption key of the source image. Required if the source
image is protected by a customer-supplied encryption key.
@ -557,7 +577,7 @@ RETURN = '''
returned: success
type: complex
contains:
raw_key:
rawKey:
description:
- Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64
to either encrypt or decrypt this resource.
@ -598,7 +618,7 @@ RETURN = '''
the default is PERSISTENT.
returned: success
type: str
machine_type:
machineType:
description:
- Reference to a gcompute_machine_type resource.
returned: success
@ -609,23 +629,23 @@ RETURN = '''
These pairs can consist of custom metadata or predefined keys.
returned: success
type: dict
guest_accelerators:
guestAccelerators:
description:
- List of the type and count of accelerator cards attached to the instance .
returned: success
type: complex
contains:
accelerator_count:
acceleratorCount:
description:
- The number of the guest accelerator cards exposed to this instance.
returned: success
type: int
accelerator_type:
acceleratorType:
description:
- Full or partial URL of the accelerator type resource to expose to this instance.
returned: success
type: str
network_interfaces:
networkInterfaces:
description:
- An array of configurations for this interface. This specifies how this interface
is configured to interact with other network services, such as connecting to the
@ -633,7 +653,7 @@ RETURN = '''
returned: success
type: complex
contains:
access_configs:
accessConfigs:
description:
- An array of configurations for this interface. Currently, only one access config,
ONE_TO_ONE_NAT, is supported. If there are no accessConfigs specified, then this
@ -648,7 +668,7 @@ RETURN = '''
IP or Network Access.
returned: success
type: str
nat_ip:
natIP:
description:
- Specifies the title of a gcompute_address.
- An external IP address associated with this instance.
@ -663,14 +683,14 @@ RETURN = '''
- The type of configuration. The default and only option is ONE_TO_ONE_NAT.
returned: success
type: str
alias_ip_ranges:
aliasIpRanges:
description:
- An array of alias IP ranges for this network interface. Can only be specified for
network interfaces on subnet-mode networks.
returned: success
type: complex
contains:
ip_cidr_range:
ipCidrRange:
description:
- The IP CIDR range represented by this alias IP range.
- This IP CIDR range must belong to the specified subnetwork and cannot contain IP
@ -679,7 +699,7 @@ RETURN = '''
(e.g. 10.1.2.0/24).
returned: success
type: str
subnetwork_range_name:
subnetworkRangeName:
description:
- Optional subnetwork secondary range name specifying the secondary range from which
to allocate the IP CIDR range for this alias IP range. If left unspecified, the
@ -700,7 +720,7 @@ RETURN = '''
is inferred.
returned: success
type: dict
network_ip:
networkIP:
description:
- An IPv4 internal network address to assign to the instance for this network interface.
If not specified by the user, an unused internal IP is assigned by the system.
@ -720,7 +740,7 @@ RETURN = '''
returned: success
type: complex
contains:
automatic_restart:
automaticRestart:
description:
- Specifies whether the instance should be automatically restarted if it is terminated
by Compute Engine (not terminated by a user).
@ -728,7 +748,7 @@ RETURN = '''
instances cannot be automatically restarted.
returned: success
type: bool
on_host_maintenance:
onHostMaintenance:
description:
- Defines the maintenance behavior for this instance. For standard instances, the
default behavior is MIGRATE. For preemptible instances, the default and only possible
@ -742,7 +762,7 @@ RETURN = '''
creation, it cannot be set or changed after the instance has been created.
returned: success
type: bool
service_accounts:
serviceAccounts:
description:
- A list of service accounts, with their specified scopes, authorized for this instance.
Only one service account per VM instance is supported.
@ -884,7 +904,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -908,8 +929,7 @@ def create(module, link, kind):
def update(module, link, kind):
auth = GcpSession(module, 'compute')
return wait_for_operation(module, auth.put(link, resource_to_request(module)))
module.fail_json(msg="InstanceTemplate cannot be edited")
def delete(module, link, kind):
@ -933,9 +953,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -946,9 +966,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/global/instanceTemplates".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -965,8 +985,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result
@ -1005,7 +1023,7 @@ def response_to_hash(module, response):
def disk_type_selflink(name, params):
if name is None:
return
url = r"https://www.googleapis.com/compute/v1/projects/.*/zones/{zone}/diskTypes/[a-z1-9\-]*"
url = r"https://www.googleapis.com/compute/v1/projects/.*/zones/[a-z1-9\-]*/diskTypes/[a-z1-9\-]*"
if not re.match(url, name):
name = "https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/diskTypes/%s".format(**params) % name
return name
@ -1049,13 +1067,13 @@ def raise_if_errors(response, err_path, module):
def encode_request(request, module):
if 'metadata' in request:
if 'metadata' in request and request['metadata'] is not None:
request['metadata'] = metadata_encoder(request['metadata'])
return request
def decode_response(response, module):
if 'metadata' in response:
if 'metadata' in response and response['metadata'] is not None:
response['metadata'] = metadata_decoder(response['metadata'])
return response

@ -56,7 +56,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -66,7 +66,7 @@ items:
returned: always
type: complex
contains:
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -93,7 +93,7 @@ items:
returned: success
type: complex
contains:
can_ip_forward:
canIpForward:
description:
- Enables instances created based on this template to send packets with source IP
addresses other than their own and receive packets with destination IP addresses
@ -115,7 +115,7 @@ items:
returned: success
type: complex
contains:
auto_delete:
autoDelete:
description:
- Specifies whether the disk will be auto-deleted when the instance is deleted (but
not when the disk is detached from the instance).
@ -129,26 +129,26 @@ items:
of the disk for its root filesystem.
returned: success
type: bool
device_name:
deviceName:
description:
- Specifies a unique device name of your choice that is reflected into the /dev/disk/by-id/google-*
tree of a Linux operating system running within the instance. This name can be used
to reference the device for mounting, resizing, and so on, from within the instance.
returned: success
type: str
disk_encryption_key:
diskEncryptionKey:
description:
- Encrypts or decrypts a disk using a customer-supplied encryption key.
returned: success
type: complex
contains:
raw_key:
rawKey:
description:
- Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64
to either encrypt or decrypt this resource.
returned: success
type: str
rsa_encrypted_key:
rsaEncryptedKey:
description:
- Specifies an RFC 4648 base64 encoded, RSA-wrapped 2048-bit customer-supplied encryption
key to either encrypt or decrypt this resource.
@ -167,7 +167,7 @@ items:
a unique index number. If not specified, the server will choose an appropriate value.
returned: success
type: int
initialize_params:
initializeParams:
description:
- Specifies the parameters for a new disk that will be created alongside the new instance.
Use initialization parameters to create boot disks or local SSDs attached to the
@ -175,32 +175,32 @@ items:
returned: success
type: complex
contains:
disk_name:
diskName:
description:
- Specifies the disk name. If not specified, the default is to use the name of the
instance.
returned: success
type: str
disk_size_gb:
diskSizeGb:
description:
- Specifies the size of the disk in base-2 GB.
returned: success
type: int
disk_type:
diskType:
description:
- Reference to a gcompute_disk_type resource.
- Specifies the disk type to use to create the instance.
- If not specified, the default is pd-standard.
returned: success
type: str
source_image:
sourceImage:
description:
- The source image to create this disk. When creating a new instance, one of initializeParams.sourceImage
or disks.source is required. To create a disk with one of the public operating
system images, specify the image by its family name.
returned: success
type: str
source_image_encryption_key:
sourceImageEncryptionKey:
description:
- The customer-supplied encryption key of the source image. Required if the source
image is protected by a customer-supplied encryption key.
@ -210,7 +210,7 @@ items:
returned: success
type: complex
contains:
raw_key:
rawKey:
description:
- Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64
to either encrypt or decrypt this resource.
@ -251,7 +251,7 @@ items:
the default is PERSISTENT.
returned: success
type: str
machine_type:
machineType:
description:
- Reference to a gcompute_machine_type resource.
returned: success
@ -262,23 +262,23 @@ items:
These pairs can consist of custom metadata or predefined keys.
returned: success
type: dict
guest_accelerators:
guestAccelerators:
description:
- List of the type and count of accelerator cards attached to the instance .
returned: success
type: complex
contains:
accelerator_count:
acceleratorCount:
description:
- The number of the guest accelerator cards exposed to this instance.
returned: success
type: int
accelerator_type:
acceleratorType:
description:
- Full or partial URL of the accelerator type resource to expose to this instance.
returned: success
type: str
network_interfaces:
networkInterfaces:
description:
- An array of configurations for this interface. This specifies how this interface
is configured to interact with other network services, such as connecting to the
@ -286,7 +286,7 @@ items:
returned: success
type: complex
contains:
access_configs:
accessConfigs:
description:
- An array of configurations for this interface. Currently, only one access config,
ONE_TO_ONE_NAT, is supported. If there are no accessConfigs specified, then this
@ -301,7 +301,7 @@ items:
IP or Network Access.
returned: success
type: str
nat_ip:
natIP:
description:
- Specifies the title of a gcompute_address.
- An external IP address associated with this instance.
@ -316,14 +316,14 @@ items:
- The type of configuration. The default and only option is ONE_TO_ONE_NAT.
returned: success
type: str
alias_ip_ranges:
aliasIpRanges:
description:
- An array of alias IP ranges for this network interface. Can only be specified for
network interfaces on subnet-mode networks.
returned: success
type: complex
contains:
ip_cidr_range:
ipCidrRange:
description:
- The IP CIDR range represented by this alias IP range.
- This IP CIDR range must belong to the specified subnetwork and cannot contain IP
@ -332,7 +332,7 @@ items:
(e.g. 10.1.2.0/24).
returned: success
type: str
subnetwork_range_name:
subnetworkRangeName:
description:
- Optional subnetwork secondary range name specifying the secondary range from which
to allocate the IP CIDR range for this alias IP range. If left unspecified, the
@ -353,7 +353,7 @@ items:
is inferred.
returned: success
type: dict
network_ip:
networkIP:
description:
- An IPv4 internal network address to assign to the instance for this network interface.
If not specified by the user, an unused internal IP is assigned by the system.
@ -373,7 +373,7 @@ items:
returned: success
type: complex
contains:
automatic_restart:
automaticRestart:
description:
- Specifies whether the instance should be automatically restarted if it is terminated
by Compute Engine (not terminated by a user).
@ -381,7 +381,7 @@ items:
instances cannot be automatically restarted.
returned: success
type: bool
on_host_maintenance:
onHostMaintenance:
description:
- Defines the maintenance behavior for this instance. For standard instances, the
default behavior is MIGRATE. For preemptible instances, the default and only possible
@ -395,7 +395,7 @@ items:
creation, it cannot be set or changed after the instance has been created.
returned: success
type: bool
service_accounts:
serviceAccounts:
description:
- A list of service accounts, with their specified scopes, authorized for this instance.
Only one service account per VM instance is supported.
@ -451,7 +451,7 @@ import json
def main():
module = GcpModule(
argument_spec=dict(
filters=dict(type='list', elements='str'),
filters=dict(type='list', elements='str')
)
)

@ -62,12 +62,6 @@ options:
- An optional description of this resource. Provide this property when you create
the resource.
required: false
gateway_ipv4:
description:
- A gateway address for default routing to other networks. This value is read only
and is selected by the Google Compute Engine, typically as the first usable address
in the IPv4Range.
required: false
ipv4_range:
description:
- 'The range of internal addresses that are legal on this network. This range is a
@ -82,7 +76,7 @@ options:
which means the first character must be a lowercase letter, and all following characters
must be a dash, lowercase letter, or digit, except the last character, which cannot
be a dash.
required: false
required: true
auto_create_subnetworks:
description:
- When set to true, the network is created in "auto subnet mode". When set to false,
@ -91,7 +85,25 @@ options:
and it automatically creates one subnetwork per region.
required: false
type: bool
routing_config:
description:
- The network-level routing configuration for this network. Used by Cloud Router to
determine what type of network-wide routing behavior to enforce.
required: false
version_added: 2.8
suboptions:
routing_mode:
description:
- The network-wide routing mode to use. If set to REGIONAL, this network's cloud routers
will only advertise routes with subnetworks of this network in the same region as
the router. If set to GLOBAL, this network's cloud routers will advertise routes
with all subnetworks of this network, across regions.
required: true
choices: ['REGIONAL', 'GLOBAL']
extends_documentation_fragment: gcp
notes:
- "API Reference: U(https://cloud.google.com/compute/docs/reference/rest/v1/networks)"
- "Official Documentation: U(https://cloud.google.com/vpc/docs/vpc)"
'''
EXAMPLES = '''
@ -100,7 +112,7 @@ EXAMPLES = '''
name: "test_object"
auto_create_subnetworks: true
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
@ -146,7 +158,7 @@ RETURN = '''
- Server-defined fully-qualified URLs for all subnetworks in this network.
returned: success
type: list
auto_create_subnetworks:
autoCreateSubnetworks:
description:
- When set to true, the network is created in "auto subnet mode". When set to false,
the network is in "custom subnet mode".
@ -154,18 +166,33 @@ RETURN = '''
and it automatically creates one subnetwork per region.
returned: success
type: bool
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
type: str
routingConfig:
description:
- The network-level routing configuration for this network. Used by Cloud Router to
determine what type of network-wide routing behavior to enforce.
returned: success
type: complex
contains:
routingMode:
description:
- The network-wide routing mode to use. If set to REGIONAL, this network's cloud routers
will only advertise routes with subnetworks of this network in the same region as
the router. If set to GLOBAL, this network's cloud routers will advertise routes
with all subnetworks of this network, across regions.
returned: success
type: str
'''
################################################################################
# Imports
################################################################################
from ansible.module_utils.gcp_utils import navigate_hash, GcpSession, GcpModule, GcpRequest, replace_resource_dict
from ansible.module_utils.gcp_utils import navigate_hash, GcpSession, GcpModule, GcpRequest, remove_nones_from_dict, replace_resource_dict
import json
import time
@ -181,10 +208,12 @@ def main():
argument_spec=dict(
state=dict(default='present', choices=['present', 'absent'], type='str'),
description=dict(type='str'),
gateway_ipv4=dict(type='str'),
ipv4_range=dict(type='str'),
name=dict(type='str'),
auto_create_subnetworks=dict(type='bool')
name=dict(required=True, type='str'),
auto_create_subnetworks=dict(type='bool'),
routing_config=dict(type='list', elements='dict', options=dict(
routing_mode=dict(required=True, type='str', choices=['REGIONAL', 'GLOBAL'])
))
)
)
@ -200,7 +229,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind, fetch)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -223,9 +253,29 @@ def create(module, link, kind):
return wait_for_operation(module, auth.post(link, resource_to_request(module)))
def update(module, link, kind):
def update(module, link, kind, fetch):
update_fields(module, resource_to_request(module),
response_to_hash(module, fetch))
auth = GcpSession(module, 'compute')
return wait_for_operation(module, auth.put(link, resource_to_request(module)))
return wait_for_operation(module, auth.patch(link, resource_to_request(module)))
def update_fields(module, request, response):
if response.get('routingConfig') != request.get('routingConfig'):
routing_config_update(module, request, response)
def routing_config_update(module, request, response):
auth = GcpSession(module, 'compute')
auth.patch(
''.join([
"https://www.googleapis.com/compute/v1/",
"projects/{project}/regions/{region}/subnetworks/{name}"
]).format(**module.params),
{
u'routingConfig': NetworkRoutingConfigArray(module.params.get('routing_config', []), module).to_request()
}
)
def delete(module, link, kind):
@ -237,10 +287,10 @@ def resource_to_request(module):
request = {
u'kind': 'compute#network',
u'description': module.params.get('description'),
u'gatewayIPv4': module.params.get('gateway_ipv4'),
u'IPv4Range': module.params.get('ipv4_range'),
u'name': module.params.get('name'),
u'autoCreateSubnetworks': module.params.get('auto_create_subnetworks')
u'autoCreateSubnetworks': module.params.get('auto_create_subnetworks'),
u'routingConfig': NetworkRoutingConfigArray(module.params.get('routing_config', []), module).to_request()
}
return_vals = {}
for k, v in request.items():
@ -250,9 +300,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -263,9 +313,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/global/networks".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -280,8 +330,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result
@ -308,14 +356,15 @@ def is_different(module, response):
# This is for doing comparisons with Ansible's current parameters.
def response_to_hash(module, response):
return {
u'description': response.get(u'description'),
u'description': module.params.get('description'),
u'gatewayIPv4': response.get(u'gateway_ipv4'),
u'id': response.get(u'id'),
u'IPv4Range': response.get(u'ipv4_range'),
u'name': response.get(u'name'),
u'IPv4Range': module.params.get('ipv4_range'),
u'name': module.params.get('name'),
u'subnetworks': response.get(u'subnetworks'),
u'autoCreateSubnetworks': response.get(u'autoCreateSubnetworks'),
u'creationTimestamp': response.get(u'creationTimestamp')
u'autoCreateSubnetworks': module.params.get('auto_create_subnetworks'),
u'creationTimestamp': response.get(u'creationTimestamp'),
u'routingConfig': NetworkRoutingConfigArray(response.get(u'routingConfig', []), module).from_response()
}
@ -356,5 +405,36 @@ def raise_if_errors(response, err_path, module):
module.fail_json(msg=errors)
class NetworkRoutingConfigArray(object):
def __init__(self, request, module):
self.module = module
if request:
self.request = request
else:
self.request = []
def to_request(self):
items = []
for item in self.request:
items.append(self._request_for_item(item))
return items
def from_response(self):
items = []
for item in self.request:
items.append(self._response_from_item(item))
return items
def _request_for_item(self, item):
return remove_nones_from_dict({
u'routingMode': item.get('routing_mode')
})
def _response_from_item(self, item):
return remove_nones_from_dict({
u'routingMode': item.get(u'routingMode')
})
if __name__ == '__main__':
main()

@ -56,7 +56,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -106,7 +106,7 @@ items:
- Server-defined fully-qualified URLs for all subnetworks in this network.
returned: success
type: list
auto_create_subnetworks:
autoCreateSubnetworks:
description:
- When set to true, the network is created in "auto subnet mode". When set to false,
the network is in "custom subnet mode".
@ -114,11 +114,26 @@ items:
and it automatically creates one subnetwork per region.
returned: success
type: bool
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
type: str
routingConfig:
description:
- The network-level routing configuration for this network. Used by Cloud Router to
determine what type of network-wide routing behavior to enforce.
returned: success
type: complex
contains:
routingMode:
description:
- The network-wide routing mode to use. If set to REGIONAL, this network's cloud routers
will only advertise routes with subnetworks of this network in the same region as
the router. If set to GLOBAL, this network's cloud routers will advertise routes
with all subnetworks of this network, across regions.
returned: success
type: str
'''
################################################################################
@ -135,7 +150,7 @@ import json
def main():
module = GcpModule(
argument_spec=dict(
filters=dict(type='list', elements='str'),
filters=dict(type='list', elements='str')
)
)

@ -84,6 +84,11 @@ options:
network:
description:
- The network that this route applies to.
- 'This field represents a link to a Network resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_network task
and then set this network field to "{{ name-of-resource }}" Alternatively, you can
set this network to a dictionary with the selfLink key where the value is the selfLink
of your Network.'
required: true
priority:
description:
@ -146,13 +151,13 @@ EXAMPLES = '''
- backends
- databases
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
dest_range:
destRange:
description:
- The destination range of outgoing packets that this route applies to.
- Only IPv4 is supported.
@ -193,7 +198,7 @@ RETURN = '''
- A list of instance tags to which this route applies.
returned: success
type: list
next_hop_gateway:
nextHopGateway:
description:
- URL to a gateway that should handle matching packets.
- 'Currently, you can only specify the internet gateway, using a full or partial valid
@ -202,7 +207,7 @@ RETURN = '''
.'
returned: success
type: str
next_hop_instance:
nextHopInstance:
description:
- URL to an instance that should handle matching packets.
- 'You can specify this as a full or partial URL. For example: * U(https://www.googleapis.com/compute/v1/projects/project/zones/zone/)
@ -210,17 +215,17 @@ RETURN = '''
.'
returned: success
type: str
next_hop_ip:
nextHopIp:
description:
- Network IP address of an instance that should handle matching packets.
returned: success
type: str
next_hop_vpn_tunnel:
nextHopVpnTunnel:
description:
- URL to a VpnTunnel that should handle matching packets.
returned: success
type: str
next_hop_network:
nextHopNetwork:
description:
- URL to a Network that should handle matching packets.
returned: success
@ -271,7 +276,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -295,8 +301,7 @@ def create(module, link, kind):
def update(module, link, kind):
auth = GcpSession(module, 'compute')
return wait_for_operation(module, auth.put(link, resource_to_request(module)))
module.fail_json(msg="Route cannot be edited")
def delete(module, link, kind):
@ -326,9 +331,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -339,9 +344,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/global/routes".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -356,8 +361,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result

@ -56,7 +56,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -66,7 +66,7 @@ items:
returned: always
type: complex
contains:
dest_range:
destRange:
description:
- The destination range of outgoing packets that this route applies to.
- Only IPv4 is supported.
@ -107,7 +107,7 @@ items:
- A list of instance tags to which this route applies.
returned: success
type: list
next_hop_gateway:
nextHopGateway:
description:
- URL to a gateway that should handle matching packets.
- 'Currently, you can only specify the internet gateway, using a full or partial valid
@ -116,7 +116,7 @@ items:
.'
returned: success
type: str
next_hop_instance:
nextHopInstance:
description:
- URL to an instance that should handle matching packets.
- 'You can specify this as a full or partial URL. For example: * U(https://www.googleapis.com/compute/v1/projects/project/zones/zone/)
@ -124,17 +124,17 @@ items:
.'
returned: success
type: str
next_hop_ip:
nextHopIp:
description:
- Network IP address of an instance that should handle matching packets.
returned: success
type: str
next_hop_vpn_tunnel:
nextHopVpnTunnel:
description:
- URL to a VpnTunnel that should handle matching packets.
returned: success
type: str
next_hop_network:
nextHopNetwork:
description:
- URL to a Network that should handle matching packets.
returned: success
@ -155,7 +155,7 @@ import json
def main():
module = GcpModule(
argument_spec=dict(
filters=dict(type='list', elements='str'),
filters=dict(type='list', elements='str')
)
)

@ -61,6 +61,11 @@ options:
network:
description:
- A reference to the network to which this router belongs.
- 'This field represents a link to a Network resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_network task
and then set this network field to "{{ name-of-resource }}" Alternatively, you can
set this network to a dictionary with the selfLink key where the value is the selfLink
of your Network.'
required: true
bgp:
description:
@ -138,7 +143,7 @@ EXAMPLES = '''
- range: 6.7.0.0/16
region: us-central1
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
@ -149,7 +154,7 @@ RETURN = '''
- The unique identifier for the resource.
returned: success
type: int
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -186,13 +191,13 @@ RETURN = '''
that link to this router will have the same local ASN.
returned: success
type: int
advertise_mode:
advertiseMode:
description:
- User-specified flag to indicate which mode to use for advertisement.
- 'Valid values of this enum field are: DEFAULT, CUSTOM .'
returned: success
type: str
advertised_groups:
advertisedGroups:
description:
- User-specified list of prefix groups to advertise in custom mode.
- This field can only be populated if advertiseMode is CUSTOM and is advertised to
@ -201,7 +206,7 @@ RETURN = '''
- 'This enum field has the one valid value: ALL_SUBNETS .'
returned: success
type: list
advertised_ip_ranges:
advertisedIpRanges:
description:
- User-specified list of individual IP ranges to advertise in custom mode. This field
can only be populated if advertiseMode is CUSTOM and is advertised to all peers
@ -274,7 +279,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -324,9 +330,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -337,9 +343,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/regions/{region}/routers".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -354,8 +360,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result

@ -61,7 +61,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -76,7 +76,7 @@ items:
- The unique identifier for the resource.
returned: success
type: int
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -113,13 +113,13 @@ items:
that link to this router will have the same local ASN.
returned: success
type: int
advertise_mode:
advertiseMode:
description:
- User-specified flag to indicate which mode to use for advertisement.
- 'Valid values of this enum field are: DEFAULT, CUSTOM .'
returned: success
type: str
advertised_groups:
advertisedGroups:
description:
- User-specified list of prefix groups to advertise in custom mode.
- This field can only be populated if advertiseMode is CUSTOM and is advertised to
@ -128,7 +128,7 @@ items:
- 'This enum field has the one valid value: ALL_SUBNETS .'
returned: success
type: list
advertised_ip_ranges:
advertisedIpRanges:
description:
- User-specified list of individual IP ranges to advertise in custom mode. This field
can only be populated if advertiseMode is CUSTOM and is advertised to all peers

@ -32,8 +32,9 @@ DOCUMENTATION = '''
---
module: gcp_compute_ssl_certificate
description:
- An SslCertificate resource. This resource provides a mechanism to upload an SSL
key and certificate to the load balancer to serve secure connections from the user.
- An SslCertificate resource, used for HTTPS load balancing. This resource provides
a mechanism to upload an SSL key and certificate to the load balancer to serve secure
connections from the user.
short_description: Creates a GCP SslCertificate
version_added: 2.6
author: Google Inc. (@googlecloudplatform)
@ -52,7 +53,7 @@ options:
- The certificate in PEM format.
- The certificate chain must be no greater than 5 certs long.
- The chain must include at least one intermediate cert.
required: false
required: true
description:
description:
- An optional description of this resource.
@ -68,9 +69,12 @@ options:
required: false
private_key:
description:
- The private key in PEM format.
required: false
- The write-only private key in PEM format.
required: true
extends_documentation_fragment: gcp
notes:
- "API Reference: U(https://cloud.google.com/compute/docs/reference/rest/v1/sslCertificates)"
- "Official Documentation: U(https://cloud.google.com/load-balancing/docs/ssl-certificates)"
'''
EXAMPLES = '''
@ -103,7 +107,7 @@ EXAMPLES = '''
OGN02HtkpBOZzzvUARTR10JQoSe2/5PIwQ==
-----END EC PRIVATE KEY-----
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
@ -116,7 +120,7 @@ RETURN = '''
- The chain must include at least one intermediate cert.
returned: success
type: str
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -141,9 +145,9 @@ RETURN = '''
be a dash.
returned: success
type: str
private_key:
privateKey:
description:
- The private key in PEM format.
- The write-only private key in PEM format.
returned: success
type: str
'''
@ -167,10 +171,10 @@ def main():
module = GcpModule(
argument_spec=dict(
state=dict(default='present', choices=['present', 'absent'], type='str'),
certificate=dict(type='str'),
certificate=dict(required=True, type='str'),
description=dict(type='str'),
name=dict(type='str'),
private_key=dict(type='str')
private_key=dict(required=True, type='str')
)
)
@ -186,7 +190,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -210,8 +215,7 @@ def create(module, link, kind):
def update(module, link, kind):
auth = GcpSession(module, 'compute')
return wait_for_operation(module, auth.put(link, resource_to_request(module)))
module.fail_json(msg="SslCertificate cannot be edited")
def delete(module, link, kind):
@ -235,9 +239,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -248,9 +252,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/global/sslCertificates".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -265,8 +269,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result

@ -56,7 +56,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -73,7 +73,7 @@ items:
- The chain must include at least one intermediate cert.
returned: success
type: str
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -98,9 +98,9 @@ items:
be a dash.
returned: success
type: str
private_key:
privateKey:
description:
- The private key in PEM format.
- The write-only private key in PEM format.
returned: success
type: str
'''
@ -119,7 +119,7 @@ import json
def main():
module = GcpModule(
argument_spec=dict(
filters=dict(type='list', elements='str'),
filters=dict(type='list', elements='str')
)
)

@ -96,13 +96,13 @@ EXAMPLES = '''
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -135,18 +135,18 @@ RETURN = '''
in the `customFeatures` field.
returned: success
type: str
min_tls_version:
minTlsVersion:
description:
- The minimum version of SSL protocol that can be used by the clients to establish
a connection with the load balancer. This can be one of `TLS_1_0`, `TLS_1_1`, `TLS_1_2`.
returned: success
type: str
enabled_features:
enabledFeatures:
description:
- The list of features enabled in the SSL policy.
returned: success
type: list
custom_features:
customFeatures:
description:
- A list of features enabled when the selected profile is CUSTOM. The method returns
the set of features that can be specified in this list. This field must be empty
@ -217,7 +217,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -267,9 +268,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -280,9 +281,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/global/sslPolicies".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -297,8 +298,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result

@ -56,7 +56,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -66,7 +66,7 @@ items:
returned: always
type: complex
contains:
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -99,18 +99,18 @@ items:
in the `customFeatures` field.
returned: success
type: str
min_tls_version:
minTlsVersion:
description:
- The minimum version of SSL protocol that can be used by the clients to establish
a connection with the load balancer. This can be one of `TLS_1_0`, `TLS_1_1`, `TLS_1_2`.
returned: success
type: str
enabled_features:
enabledFeatures:
description:
- The list of features enabled in the SSL policy.
returned: success
type: list
custom_features:
customFeatures:
description:
- A list of features enabled when the selected profile is CUSTOM. The method returns
the set of features that can be specified in this list. This field must be empty
@ -156,7 +156,7 @@ import json
def main():
module = GcpModule(
argument_spec=dict(
filters=dict(type='list', elements='str'),
filters=dict(type='list', elements='str')
)
)

@ -87,7 +87,39 @@ options:
description:
- The network this subnet belongs to.
- Only networks that are in the distributed mode can have subnetworks.
- 'This field represents a link to a Network resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_network task
and then set this network field to "{{ name-of-resource }}" Alternatively, you can
set this network to a dictionary with the selfLink key where the value is the selfLink
of your Network.'
required: true
enable_flow_logs:
description:
- Whether to enable flow logging for this subnetwork.
required: false
type: bool
version_added: 2.8
secondary_ip_ranges:
description:
- An array of configurations for secondary IP ranges for VM instances contained in
this subnetwork. The primary IP of such VM must belong to the primary ipCidrRange
of the subnetwork. The alias IPs may belong to either primary or secondary ranges.
required: false
version_added: 2.8
suboptions:
range_name:
description:
- The name associated with this subnetwork secondary range, used when adding an alias
IP range to a VM instance. The name must be 1-63 characters long, and comply with
RFC1035. The name must be unique within the subnetwork.
required: true
ip_cidr_range:
description:
- The range of IP addresses belonging to this subnetwork secondary range. Provide
this property when you create the subnetwork.
- Ranges must be unique and non-overlapping with all primary and secondary IP ranges
within a network. Only IPv4 is supported.
required: true
private_ip_google_access:
description:
- Whether the VMs in this subnet can access Google services without assigned external
@ -123,13 +155,13 @@ EXAMPLES = '''
network: "{{ network }}"
ip_cidr_range: 172.16.0.0/16
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -140,7 +172,7 @@ RETURN = '''
the resource. This field can be set only at resource creation time.
returned: success
type: str
gateway_address:
gatewayAddress:
description:
- The gateway address for default routes to reach destination addresses outside this
subnetwork.
@ -151,7 +183,7 @@ RETURN = '''
- The unique identifier for the resource.
returned: success
type: int
ip_cidr_range:
ipCidrRange:
description:
- The range of internal addresses that are owned by this subnetwork.
- Provide this property when you create the subnetwork. For example, 10.0.0.0/8 or
@ -175,7 +207,41 @@ RETURN = '''
- Only networks that are in the distributed mode can have subnetworks.
returned: success
type: dict
private_ip_google_access:
enableFlowLogs:
description:
- Whether to enable flow logging for this subnetwork.
returned: success
type: bool
fingerprint:
description:
- Fingerprint of this resource. This field is used internally during updates of this
resource.
returned: success
type: str
secondaryIpRanges:
description:
- An array of configurations for secondary IP ranges for VM instances contained in
this subnetwork. The primary IP of such VM must belong to the primary ipCidrRange
of the subnetwork. The alias IPs may belong to either primary or secondary ranges.
returned: success
type: complex
contains:
rangeName:
description:
- The name associated with this subnetwork secondary range, used when adding an alias
IP range to a VM instance. The name must be 1-63 characters long, and comply with
RFC1035. The name must be unique within the subnetwork.
returned: success
type: str
ipCidrRange:
description:
- The range of IP addresses belonging to this subnetwork secondary range. Provide
this property when you create the subnetwork.
- Ranges must be unique and non-overlapping with all primary and secondary IP ranges
within a network. Only IPv4 is supported.
returned: success
type: str
privateIpGoogleAccess:
description:
- Whether the VMs in this subnet can access Google services without assigned external
IP addresses.
@ -192,7 +258,7 @@ RETURN = '''
# Imports
################################################################################
from ansible.module_utils.gcp_utils import navigate_hash, GcpSession, GcpModule, GcpRequest, replace_resource_dict
from ansible.module_utils.gcp_utils import navigate_hash, GcpSession, GcpModule, GcpRequest, remove_nones_from_dict, replace_resource_dict
import json
import time
@ -211,6 +277,11 @@ def main():
ip_cidr_range=dict(required=True, type='str'),
name=dict(required=True, type='str'),
network=dict(required=True, type='dict'),
enable_flow_logs=dict(type='bool'),
secondary_ip_ranges=dict(type='list', elements='dict', options=dict(
range_name=dict(required=True, type='str'),
ip_cidr_range=dict(required=True, type='str')
)),
private_ip_google_access=dict(type='bool'),
region=dict(required=True, type='str')
)
@ -228,7 +299,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind, fetch)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -251,9 +323,60 @@ def create(module, link, kind):
return wait_for_operation(module, auth.post(link, resource_to_request(module)))
def update(module, link, kind):
def update(module, link, kind, fetch):
update_fields(module, resource_to_request(module),
response_to_hash(module, fetch))
return fetch_resource(module, self_link(module), kind)
def update_fields(module, request, response):
if response.get('ipCidrRange') != request.get('ipCidrRange'):
ip_cidr_range_update(module, request, response)
if response.get('enableFlowLogs') != request.get('enableFlowLogs') or response.get('secondaryIpRanges') != request.get('secondaryIpRanges'):
enable_flow_logs_update(module, request, response)
if response.get('privateIpGoogleAccess') != request.get('privateIpGoogleAccess'):
private_ip_google_access_update(module, request, response)
def ip_cidr_range_update(module, request, response):
auth = GcpSession(module, 'compute')
auth.post(
''.join([
"https://www.googleapis.com/compute/v1/",
"projects/{project}/regions/{region}/subnetworks/{name}/expandIpCidrRange"
]).format(**module.params),
{
u'ipCidrRange': module.params.get('ip_cidr_range')
}
)
def enable_flow_logs_update(module, request, response):
auth = GcpSession(module, 'compute')
return wait_for_operation(module, auth.put(link, resource_to_request(module)))
auth.patch(
''.join([
"https://www.googleapis.com/compute/v1/",
"projects/{project}/regions/{region}/subnetworks/{name}"
]).format(**module.params),
{
u'enableFlowLogs': module.params.get('enable_flow_logs'),
u'fingerprint': response.get('fingerprint'),
u'secondaryIpRanges': SubnetworkSecondaryIpRangesArray(module.params.get('secondary_ip_ranges', []), module).to_request()
}
)
def private_ip_google_access_update(module, request, response):
auth = GcpSession(module, 'compute')
auth.post(
''.join([
"https://www.googleapis.com/compute/v1/",
"projects/{project}/regions/{region}/subnetworks/{name}/setPrivateIpGoogleAccess"
]).format(**module.params),
{
u'privateIpGoogleAccess': module.params.get('private_ip_google_access')
}
)
def delete(module, link, kind):
@ -268,6 +391,8 @@ def resource_to_request(module):
u'ipCidrRange': module.params.get('ip_cidr_range'),
u'name': module.params.get('name'),
u'network': replace_resource_dict(module.params.get(u'network', {}), 'selfLink'),
u'enableFlowLogs': module.params.get('enable_flow_logs'),
u'secondaryIpRanges': SubnetworkSecondaryIpRangesArray(module.params.get('secondary_ip_ranges', []), module).to_request(),
u'privateIpGoogleAccess': module.params.get('private_ip_google_access'),
u'region': module.params.get('region')
}
@ -279,9 +404,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -292,9 +417,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/regions/{region}/subnetworks".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -309,8 +434,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result
@ -344,6 +467,9 @@ def response_to_hash(module, response):
u'ipCidrRange': response.get(u'ipCidrRange'),
u'name': response.get(u'name'),
u'network': replace_resource_dict(module.params.get(u'network', {}), 'selfLink'),
u'enableFlowLogs': response.get(u'enableFlowLogs'),
u'fingerprint': response.get(u'fingerprint'),
u'secondaryIpRanges': SubnetworkSecondaryIpRangesArray(response.get(u'secondaryIpRanges', []), module).from_response(),
u'privateIpGoogleAccess': response.get(u'privateIpGoogleAccess'),
u'region': module.params.get('region')
}
@ -386,5 +512,38 @@ def raise_if_errors(response, err_path, module):
module.fail_json(msg=errors)
class SubnetworkSecondaryIpRangesArray(object):
def __init__(self, request, module):
self.module = module
if request:
self.request = request
else:
self.request = []
def to_request(self):
items = []
for item in self.request:
items.append(self._request_for_item(item))
return items
def from_response(self):
items = []
for item in self.request:
items.append(self._response_from_item(item))
return items
def _request_for_item(self, item):
return remove_nones_from_dict({
u'rangeName': item.get('range_name'),
u'ipCidrRange': item.get('ip_cidr_range')
})
def _response_from_item(self, item):
return remove_nones_from_dict({
u'rangeName': item.get(u'rangeName'),
u'ipCidrRange': item.get(u'ipCidrRange')
})
if __name__ == '__main__':
main()

@ -61,7 +61,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -71,7 +71,7 @@ items:
returned: always
type: complex
contains:
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -82,7 +82,7 @@ items:
the resource. This field can be set only at resource creation time.
returned: success
type: str
gateway_address:
gatewayAddress:
description:
- The gateway address for default routes to reach destination addresses outside this
subnetwork.
@ -93,7 +93,7 @@ items:
- The unique identifier for the resource.
returned: success
type: int
ip_cidr_range:
ipCidrRange:
description:
- The range of internal addresses that are owned by this subnetwork.
- Provide this property when you create the subnetwork. For example, 10.0.0.0/8 or
@ -117,7 +117,41 @@ items:
- Only networks that are in the distributed mode can have subnetworks.
returned: success
type: dict
private_ip_google_access:
enableFlowLogs:
description:
- Whether to enable flow logging for this subnetwork.
returned: success
type: bool
fingerprint:
description:
- Fingerprint of this resource. This field is used internally during updates of this
resource.
returned: success
type: str
secondaryIpRanges:
description:
- An array of configurations for secondary IP ranges for VM instances contained in
this subnetwork. The primary IP of such VM must belong to the primary ipCidrRange
of the subnetwork. The alias IPs may belong to either primary or secondary ranges.
returned: success
type: complex
contains:
rangeName:
description:
- The name associated with this subnetwork secondary range, used when adding an alias
IP range to a VM instance. The name must be 1-63 characters long, and comply with
RFC1035. The name must be unique within the subnetwork.
returned: success
type: str
ipCidrRange:
description:
- The range of IP addresses belonging to this subnetwork secondary range. Provide
this property when you create the subnetwork.
- Ranges must be unique and non-overlapping with all primary and secondary IP ranges
within a network. Only IPv4 is supported.
returned: success
type: str
privateIpGoogleAccess:
description:
- Whether the VMs in this subnet can access Google services without assigned external
IP addresses.

@ -63,6 +63,11 @@ options:
url_map:
description:
- A reference to the UrlMap resource that defines the mapping from URL to the BackendService.
- 'This field represents a link to a UrlMap resource in GCP. It can be specified in
two ways. You can add `register: name-of-resource` to a gcp_compute_url_map task
and then set this url_map field to "{{ name-of-resource }}" Alternatively, you can
set this url_map to a dictionary with the selfLink key where the value is the selfLink
of your UrlMap.'
required: true
extends_documentation_fragment: gcp
notes:
@ -123,13 +128,13 @@ EXAMPLES = '''
name: "test_object"
url_map: "{{ urlmap }}"
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -154,7 +159,7 @@ RETURN = '''
be a dash.
returned: success
type: str
url_map:
urlMap:
description:
- A reference to the UrlMap resource that defines the mapping from URL to the BackendService.
returned: success
@ -198,7 +203,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind, fetch)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -221,9 +227,28 @@ def create(module, link, kind):
return wait_for_operation(module, auth.post(link, resource_to_request(module)))
def update(module, link, kind):
def update(module, link, kind, fetch):
update_fields(module, resource_to_request(module),
response_to_hash(module, fetch))
return fetch_resource(module, self_link(module), kind)
def update_fields(module, request, response):
if response.get('urlMap') != request.get('urlMap'):
url_map_update(module, request, response)
def url_map_update(module, request, response):
auth = GcpSession(module, 'compute')
return wait_for_operation(module, auth.put(link, resource_to_request(module)))
auth.post(
''.join([
"https://www.googleapis.com/compute/v1/",
"projects/{project}/targetHttpProxies/{name}/setUrlMap"
]).format(**module.params),
{
u'urlMap': replace_resource_dict(module.params.get(u'url_map', {}), 'selfLink')
}
)
def delete(module, link, kind):
@ -246,9 +271,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -259,9 +284,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/global/targetHttpProxies".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -276,8 +301,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result

@ -56,7 +56,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -66,7 +66,7 @@ items:
returned: always
type: complex
contains:
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -91,7 +91,7 @@ items:
be a dash.
returned: success
type: str
url_map:
urlMap:
description:
- A reference to the UrlMap resource that defines the mapping from URL to the BackendService.
returned: success
@ -112,7 +112,7 @@ import json
def main():
module = GcpModule(
argument_spec=dict(
filters=dict(type='list', elements='str'),
filters=dict(type='list', elements='str')
)
)

@ -78,6 +78,11 @@ options:
url_map:
description:
- A reference to the UrlMap resource that defines the mapping from URL to the BackendService.
- 'This field represents a link to a UrlMap resource in GCP. It can be specified in
two ways. You can add `register: name-of-resource` to a gcp_compute_url_map task
and then set this url_map field to "{{ name-of-resource }}" Alternatively, you can
set this url_map to a dictionary with the selfLink key where the value is the selfLink
of your UrlMap.'
required: true
extends_documentation_fragment: gcp
notes:
@ -174,13 +179,13 @@ EXAMPLES = '''
- "{{ sslcert }}"
url_map: "{{ urlmap }}"
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -205,7 +210,7 @@ RETURN = '''
be a dash.
returned: success
type: str
quic_override:
quicOverride:
description:
- Specifies the QUIC override policy for this resource. This determines whether the
load balancer will attempt to negotiate QUIC with clients or not. Can specify one
@ -214,13 +219,13 @@ RETURN = '''
to specifying NONE.
returned: success
type: str
ssl_certificates:
sslCertificates:
description:
- A list of SslCertificate resources that are used to authenticate connections between
users and the load balancer. Currently, exactly one SSL certificate must be specified.
returned: success
type: list
url_map:
urlMap:
description:
- A reference to the UrlMap resource that defines the mapping from URL to the BackendService.
returned: success
@ -266,7 +271,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind, fetch)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -289,9 +295,58 @@ def create(module, link, kind):
return wait_for_operation(module, auth.post(link, resource_to_request(module)))
def update(module, link, kind):
def update(module, link, kind, fetch):
update_fields(module, resource_to_request(module),
response_to_hash(module, fetch))
return fetch_resource(module, self_link(module), kind)
def update_fields(module, request, response):
if response.get('quicOverride') != request.get('quicOverride'):
quic_override_update(module, request, response)
if response.get('sslCertificates') != request.get('sslCertificates'):
ssl_certificates_update(module, request, response)
if response.get('urlMap') != request.get('urlMap'):
url_map_update(module, request, response)
def quic_override_update(module, request, response):
auth = GcpSession(module, 'compute')
auth.post(
''.join([
"https://www.googleapis.com/compute/v1/",
"projects/{project}/global/targetHttpsProxies/{name}/setQuicOverride"
]).format(**module.params),
{
u'quicOverride': module.params.get('quic_override')
}
)
def ssl_certificates_update(module, request, response):
auth = GcpSession(module, 'compute')
auth.post(
''.join([
"https://www.googleapis.com/compute/v1/",
"projects/{project}/targetHttpsProxies/{name}/setSslCertificates"
]).format(**module.params),
{
u'sslCertificates': replace_resource_dict(module.params.get('ssl_certificates', []), 'selfLink')
}
)
def url_map_update(module, request, response):
auth = GcpSession(module, 'compute')
return wait_for_operation(module, auth.put(link, resource_to_request(module)))
auth.post(
''.join([
"https://www.googleapis.com/compute/v1/",
"projects/{project}/targetHttpsProxies/{name}/setUrlMap"
]).format(**module.params),
{
u'urlMap': replace_resource_dict(module.params.get(u'url_map', {}), 'selfLink')
}
)
def delete(module, link, kind):
@ -316,9 +371,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -329,9 +384,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/global/targetHttpsProxies".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -346,8 +401,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result

@ -56,7 +56,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -66,7 +66,7 @@ items:
returned: always
type: complex
contains:
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -91,7 +91,7 @@ items:
be a dash.
returned: success
type: str
quic_override:
quicOverride:
description:
- Specifies the QUIC override policy for this resource. This determines whether the
load balancer will attempt to negotiate QUIC with clients or not. Can specify one
@ -100,13 +100,13 @@ items:
to specifying NONE.
returned: success
type: str
ssl_certificates:
sslCertificates:
description:
- A list of SslCertificate resources that are used to authenticate connections between
users and the load balancer. Currently, exactly one SSL certificate must be specified.
returned: success
type: list
url_map:
urlMap:
description:
- A reference to the UrlMap resource that defines the mapping from URL to the BackendService.
returned: success
@ -127,7 +127,7 @@ import json
def main():
module = GcpModule(
argument_spec=dict(
filters=dict(type='list', elements='str'),
filters=dict(type='list', elements='str')
)
)

@ -59,6 +59,11 @@ options:
the backup pool are unhealthy, the traffic will be directed back to the primary
pool in the "force" mode, where traffic will be spread to the healthy instances
with the best effort, or to all instances when no instance is healthy.
- 'This field represents a link to a TargetPool resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_target_pool
task and then set this backup_pool field to "{{ name-of-resource }}" Alternatively,
you can set this backup_pool to a dictionary with the selfLink key where the value
is the selfLink of your TargetPool.'
required: false
description:
description:
@ -84,6 +89,11 @@ options:
- A member instance in this pool is considered healthy if and only if the health checks
pass. If not specified it means all member instances will be considered healthy
at all times.
- 'This field represents a link to a HttpHealthCheck resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_http_health_check
task and then set this health_check field to "{{ name-of-resource }}" Alternatively,
you can set this health_check to a dictionary with the selfLink key where the value
is the selfLink of your HttpHealthCheck.'
required: false
instances:
description:
@ -125,13 +135,13 @@ EXAMPLES = '''
name: "test_object"
region: us-west1
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
backup_pool:
backupPool:
description:
- This field is applicable only when the containing target pool is serving a forwarding
rule as the primary pool, and its failoverRatio field is properly set to a value
@ -146,7 +156,7 @@ RETURN = '''
with the best effort, or to all instances when no instance is healthy.
returned: success
type: dict
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -156,7 +166,7 @@ RETURN = '''
- An optional description of this resource.
returned: success
type: str
failover_ratio:
failoverRatio:
description:
- This field is applicable only when the containing target pool is serving a forwarding
rule as the primary pool (i.e., not as a backup pool to some other target pool).
@ -171,7 +181,7 @@ RETURN = '''
or to all instances when no instance is healthy.
returned: success
type: str
health_check:
healthCheck:
description:
- A reference to a HttpHealthCheck resource.
- A member instance in this pool is considered healthy if and only if the health checks
@ -200,7 +210,7 @@ RETURN = '''
be a dash.
returned: success
type: str
session_affinity:
sessionAffinity:
description:
- 'Session affinity option. Must be one of these values: - NONE: Connections from
the same client IP may go to any instance in the pool.'
@ -259,7 +269,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -312,9 +323,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -325,9 +336,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/regions/{region}/targetPools".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -344,8 +355,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result

@ -61,7 +61,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -71,7 +71,7 @@ items:
returned: always
type: complex
contains:
backup_pool:
backupPool:
description:
- This field is applicable only when the containing target pool is serving a forwarding
rule as the primary pool, and its failoverRatio field is properly set to a value
@ -86,7 +86,7 @@ items:
with the best effort, or to all instances when no instance is healthy.
returned: success
type: dict
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -96,7 +96,7 @@ items:
- An optional description of this resource.
returned: success
type: str
failover_ratio:
failoverRatio:
description:
- This field is applicable only when the containing target pool is serving a forwarding
rule as the primary pool (i.e., not as a backup pool to some other target pool).
@ -111,7 +111,7 @@ items:
or to all instances when no instance is healthy.
returned: success
type: str
health_check:
healthCheck:
description:
- A reference to a HttpHealthCheck resource.
- A member instance in this pool is considered healthy if and only if the health checks
@ -140,7 +140,7 @@ items:
be a dash.
returned: success
type: str
session_affinity:
sessionAffinity:
description:
- 'Session affinity option. Must be one of these values: - NONE: Connections from
the same client IP may go to any instance in the pool.'

@ -56,7 +56,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -66,7 +66,7 @@ items:
returned: always
type: complex
contains:
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -91,7 +91,7 @@ items:
be a dash.
returned: success
type: str
proxy_header:
proxyHeader:
description:
- Specifies the type of proxy header to append before sending data to the backend,
either NONE or PROXY_V1. The default is NONE.
@ -102,7 +102,7 @@ items:
- A reference to the BackendService resource.
returned: success
type: dict
ssl_certificates:
sslCertificates:
description:
- A list of SslCertificate resources that are used to authenticate connections between
users and the load balancer. Currently, exactly one SSL certificate must be specified.
@ -124,7 +124,7 @@ import json
def main():
module = GcpModule(
argument_spec=dict(
filters=dict(type='list', elements='str'),
filters=dict(type='list', elements='str')
)
)

@ -69,6 +69,11 @@ options:
service:
description:
- A reference to the BackendService resource.
- 'This field represents a link to a BackendService resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_backend_service
task and then set this service field to "{{ name-of-resource }}" Alternatively,
you can set this service to a dictionary with the selfLink key where the value is
the selfLink of your BackendService.'
required: true
extends_documentation_fragment: gcp
notes:
@ -124,13 +129,13 @@ EXAMPLES = '''
proxy_header: PROXY_V1
service: "{{ backendservice }}"
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -155,7 +160,7 @@ RETURN = '''
be a dash.
returned: success
type: str
proxy_header:
proxyHeader:
description:
- Specifies the type of proxy header to append before sending data to the backend,
either NONE or PROXY_V1. The default is NONE.
@ -206,7 +211,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind, fetch)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -229,9 +235,43 @@ def create(module, link, kind):
return wait_for_operation(module, auth.post(link, resource_to_request(module)))
def update(module, link, kind):
def update(module, link, kind, fetch):
update_fields(module, resource_to_request(module),
response_to_hash(module, fetch))
return fetch_resource(module, self_link(module), kind)
def update_fields(module, request, response):
if response.get('proxyHeader') != request.get('proxyHeader'):
proxy_header_update(module, request, response)
if response.get('service') != request.get('service'):
service_update(module, request, response)
def proxy_header_update(module, request, response):
auth = GcpSession(module, 'compute')
return wait_for_operation(module, auth.put(link, resource_to_request(module)))
auth.post(
''.join([
"https://www.googleapis.com/compute/v1/",
"projects/{project}/global/targetTcpProxies/{name}/setProxyHeader"
]).format(**module.params),
{
u'proxyHeader': module.params.get('proxy_header')
}
)
def service_update(module, request, response):
auth = GcpSession(module, 'compute')
auth.post(
''.join([
"https://www.googleapis.com/compute/v1/",
"projects/{project}/global/targetTcpProxies/{name}/setBackendService"
]).format(**module.params),
{
u'service': replace_resource_dict(module.params.get(u'service', {}), 'selfLink')
}
)
def delete(module, link, kind):
@ -255,9 +295,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -268,9 +308,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/global/targetTcpProxies".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -285,8 +325,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result

@ -56,7 +56,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -66,7 +66,7 @@ items:
returned: always
type: complex
contains:
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -91,7 +91,7 @@ items:
be a dash.
returned: success
type: str
proxy_header:
proxyHeader:
description:
- Specifies the type of proxy header to append before sending data to the backend,
either NONE or PROXY_V1. The default is NONE.
@ -118,7 +118,7 @@ import json
def main():
module = GcpModule(
argument_spec=dict(
filters=dict(type='list', elements='str'),
filters=dict(type='list', elements='str')
)
)

@ -63,6 +63,11 @@ options:
network:
description:
- The network this VPN gateway is accepting traffic for.
- 'This field represents a link to a Network resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_network task
and then set this network field to "{{ name-of-resource }}" Alternatively, you can
set this network to a dictionary with the selfLink key where the value is the selfLink
of your Network.'
required: true
region:
description:
@ -99,13 +104,13 @@ EXAMPLES = '''
region: us-west1
network: "{{ network }}"
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -140,7 +145,7 @@ RETURN = '''
- A list of references to VpnTunnel resources associated to this VPN gateway.
returned: success
type: list
forwarding_rules:
forwardingRules:
description:
- A list of references to the ForwardingRule resources associated to this VPN gateway.
returned: success
@ -190,7 +195,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -214,8 +220,7 @@ def create(module, link, kind):
def update(module, link, kind):
auth = GcpSession(module, 'compute')
return wait_for_operation(module, auth.put(link, resource_to_request(module)))
module.fail_json(msg="TargetVpnGateway cannot be edited")
def delete(module, link, kind):
@ -238,9 +243,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -251,9 +256,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/regions/{region}/targetVpnGateways".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -268,8 +273,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result

@ -61,7 +61,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -71,7 +71,7 @@ items:
returned: always
type: complex
contains:
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -106,7 +106,7 @@ items:
- A list of references to VpnTunnel resources associated to this VPN gateway.
returned: success
type: list
forwarding_rules:
forwardingRules:
description:
- A list of references to the ForwardingRule resources associated to this VPN gateway.
returned: success

@ -50,6 +50,11 @@ options:
default_service:
description:
- A reference to BackendService resource if none of the hostRules match.
- 'This field represents a link to a BackendService resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_backend_service
task and then set this default_service field to "{{ name-of-resource }}" Alternatively,
you can set this default_service to a dictionary with the selfLink key where the
value is the selfLink of your BackendService.'
required: true
description:
description:
@ -71,12 +76,12 @@ options:
- The list of host patterns to match. They must be valid hostnames, except * will
match any string of ([a-z0-9-.]*). In that case, * must be the first character and
must be followed in the pattern by either - or .
required: false
required: true
path_matcher:
description:
- The name of the PathMatcher to use to match the path portion of the URL if the hostRule
matches the URL's host portion.
required: false
required: true
name:
description:
- Name of the resource. Provided by the client when the resource is created. The name
@ -85,7 +90,7 @@ options:
which means the first character must be a lowercase letter, and all following characters
must be a dash, lowercase letter, or digit, except the last character, which cannot
be a dash.
required: false
required: true
path_matchers:
description:
- The list of named PathMatchers to use against the URL.
@ -95,7 +100,12 @@ options:
description:
- A reference to a BackendService resource. This will be used if none of the pathRules
defined by this PathMatcher is matched by the URL's path portion.
required: false
- 'This field represents a link to a BackendService resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_backend_service
task and then set this default_service field to "{{ name-of-resource }}" Alternatively,
you can set this default_service to a dictionary with the selfLink key where the
value is the selfLink of your BackendService.'
required: true
description:
description:
- An optional description of this resource.
@ -103,7 +113,7 @@ options:
name:
description:
- The name to which this PathMatcher is referred by the HostRule.
required: false
required: true
path_rules:
description:
- The list of path rules.
@ -118,7 +128,12 @@ options:
service:
description:
- A reference to the BackendService resource if this rule is matched.
required: false
- 'This field represents a link to a BackendService resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_backend_service
task and then set this service field to "{{ name-of-resource }}" Alternatively,
you can set this service to a dictionary with the selfLink key where the value is
the selfLink of your BackendService.'
required: true
tests:
description:
- The list of expected URL mappings. Request to update this UrlMap will succeed only
@ -132,15 +147,20 @@ options:
host:
description:
- Host portion of the URL.
required: false
required: true
path:
description:
- Path portion of the URL.
required: false
required: true
service:
description:
- A reference to expected BackendService resource the given URL should be mapped to.
required: false
- 'This field represents a link to a BackendService resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_backend_service
task and then set this service field to "{{ name-of-resource }}" Alternatively,
you can set this service to a dictionary with the selfLink key where the value is
the selfLink of your BackendService.'
required: true
extends_documentation_fragment: gcp
'''
@ -187,18 +207,18 @@ EXAMPLES = '''
name: "test_object"
default_service: "{{ backendservice }}"
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
type: str
default_service:
defaultService:
description:
- A reference to BackendService resource if none of the hostRules match.
returned: success
@ -209,7 +229,7 @@ RETURN = '''
the resource.
returned: success
type: str
host_rules:
hostRules:
description:
- The list of HostRules to use against the URL.
returned: success
@ -228,7 +248,7 @@ RETURN = '''
must be followed in the pattern by either - or .
returned: success
type: list
path_matcher:
pathMatcher:
description:
- The name of the PathMatcher to use to match the path portion of the URL if the hostRule
matches the URL's host portion.
@ -239,6 +259,12 @@ RETURN = '''
- The unique identifier for the resource.
returned: success
type: int
fingerprint:
description:
- Fingerprint of this resource. This field is used internally during updates of this
resource.
returned: success
type: str
name:
description:
- Name of the resource. Provided by the client when the resource is created. The name
@ -249,13 +275,13 @@ RETURN = '''
be a dash.
returned: success
type: str
path_matchers:
pathMatchers:
description:
- The list of named PathMatchers to use against the URL.
returned: success
type: complex
contains:
default_service:
defaultService:
description:
- A reference to a BackendService resource. This will be used if none of the pathRules
defined by this PathMatcher is matched by the URL's path portion.
@ -271,7 +297,7 @@ RETURN = '''
- The name to which this PathMatcher is referred by the HostRule.
returned: success
type: str
path_rules:
pathRules:
description:
- The list of path rules.
returned: success
@ -341,24 +367,24 @@ def main():
description=dict(type='str'),
host_rules=dict(type='list', elements='dict', options=dict(
description=dict(type='str'),
hosts=dict(type='list', elements='str'),
path_matcher=dict(type='str')
hosts=dict(required=True, type='list', elements='str'),
path_matcher=dict(required=True, type='str')
)),
name=dict(type='str'),
name=dict(required=True, type='str'),
path_matchers=dict(type='list', elements='dict', options=dict(
default_service=dict(type='dict'),
default_service=dict(required=True, type='dict'),
description=dict(type='str'),
name=dict(type='str'),
name=dict(required=True, type='str'),
path_rules=dict(type='list', elements='dict', options=dict(
paths=dict(type='list', elements='str'),
service=dict(type='dict')
service=dict(required=True, type='dict')
))
)),
tests=dict(type='list', elements='dict', options=dict(
description=dict(type='str'),
host=dict(type='str'),
path=dict(type='str'),
service=dict(type='dict')
host=dict(required=True, type='str'),
path=dict(required=True, type='str'),
service=dict(required=True, type='dict')
))
)
)
@ -375,7 +401,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -426,9 +453,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -439,9 +466,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/global/urlMaps".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -456,8 +483,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result
@ -489,7 +514,8 @@ def response_to_hash(module, response):
u'description': response.get(u'description'),
u'hostRules': UrlMapHostRulesArray(response.get(u'hostRules', []), module).from_response(),
u'id': response.get(u'id'),
u'name': response.get(u'name'),
u'fingerprint': response.get(u'fingerprint'),
u'name': module.params.get('name'),
u'pathMatchers': UrlMapPathMatchersArray(response.get(u'pathMatchers', []), module).from_response(),
u'tests': UrlMapTestsArray(response.get(u'tests', []), module).from_response()
}

@ -56,7 +56,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -66,12 +66,12 @@ items:
returned: always
type: complex
contains:
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
type: str
default_service:
defaultService:
description:
- A reference to BackendService resource if none of the hostRules match.
returned: success
@ -82,7 +82,7 @@ items:
the resource.
returned: success
type: str
host_rules:
hostRules:
description:
- The list of HostRules to use against the URL.
returned: success
@ -101,7 +101,7 @@ items:
must be followed in the pattern by either - or .
returned: success
type: list
path_matcher:
pathMatcher:
description:
- The name of the PathMatcher to use to match the path portion of the URL if the hostRule
matches the URL's host portion.
@ -112,6 +112,12 @@ items:
- The unique identifier for the resource.
returned: success
type: int
fingerprint:
description:
- Fingerprint of this resource. This field is used internally during updates of this
resource.
returned: success
type: str
name:
description:
- Name of the resource. Provided by the client when the resource is created. The name
@ -122,13 +128,13 @@ items:
be a dash.
returned: success
type: str
path_matchers:
pathMatchers:
description:
- The list of named PathMatchers to use against the URL.
returned: success
type: complex
contains:
default_service:
defaultService:
description:
- A reference to a BackendService resource. This will be used if none of the pathRules
defined by this PathMatcher is matched by the URL's path portion.
@ -144,7 +150,7 @@ items:
- The name to which this PathMatcher is referred by the HostRule.
returned: success
type: str
path_rules:
pathRules:
description:
- The list of path rules.
returned: success
@ -205,7 +211,7 @@ import json
def main():
module = GcpModule(
argument_spec=dict(
filters=dict(type='list', elements='str'),
filters=dict(type='list', elements='str')
)
)

@ -61,10 +61,20 @@ options:
target_vpn_gateway:
description:
- URL of the Target VPN gateway with which this VPN tunnel is associated.
- 'This field represents a link to a TargetVpnGateway resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_compute_target_vpn_gateway
task and then set this target_vpn_gateway field to "{{ name-of-resource }}" Alternatively,
you can set this target_vpn_gateway to a dictionary with the selfLink key where
the value is the selfLink of your TargetVpnGateway.'
required: true
router:
description:
- URL of router resource to be used for dynamic routing.
- 'This field represents a link to a Router resource in GCP. It can be specified in
two ways. You can add `register: name-of-resource` to a gcp_compute_router task
and then set this router field to "{{ name-of-resource }}" Alternatively, you can
set this router to a dictionary with the selfLink key where the value is the selfLink
of your Router.'
required: false
peer_ip:
description:
@ -158,13 +168,13 @@ EXAMPLES = '''
router: "{{ router }}"
shared_secret: super secret
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -183,7 +193,7 @@ RETURN = '''
- An optional description of this resource.
returned: success
type: str
target_vpn_gateway:
targetVpnGateway:
description:
- URL of the Target VPN gateway with which this VPN tunnel is associated.
returned: success
@ -192,30 +202,30 @@ RETURN = '''
description:
- URL of router resource to be used for dynamic routing.
returned: success
type: str
peer_ip:
type: dict
peerIp:
description:
- IP address of the peer VPN gateway. Only IPv4 is supported.
returned: success
type: str
shared_secret:
sharedSecret:
description:
- Shared secret used to set the secure session between the Cloud VPN gateway and the
peer VPN gateway.
returned: success
type: str
shared_secret_hash:
sharedSecretHash:
description:
- Hash of the shared secret.
returned: success
type: str
ike_version:
ikeVersion:
description:
- IKE protocol version to use when establishing the VPN tunnel with peer VPN gateway.
- Acceptable IKE versions are 1 or 2. Default version is 2.
returned: success
type: int
local_traffic_selector:
localTrafficSelector:
description:
- Local traffic selector to use when establishing the VPN tunnel with peer VPN gateway.
The value should be a CIDR formatted string, for example `192.168.0.0/16`. The ranges
@ -223,7 +233,7 @@ RETURN = '''
- Only IPv4 is supported.
returned: success
type: list
remote_traffic_selector:
remoteTrafficSelector:
description:
- Remote traffic selector to use when establishing the VPN tunnel with peer VPN gateway.
The value should be a CIDR formatted string, for example `192.168.0.0/16`. The ranges
@ -236,6 +246,12 @@ RETURN = '''
- Labels to apply to this VpnTunnel.
returned: success
type: dict
labelFingerprint:
description:
- The fingerprint used for optimistic locking of this resource. Used internally during
updates.
returned: success
type: str
region:
description:
- The region where the tunnel is located.
@ -265,7 +281,7 @@ def main():
name=dict(required=True, type='str'),
description=dict(type='str'),
target_vpn_gateway=dict(required=True, type='dict'),
router=dict(type='str'),
router=dict(type='dict'),
peer_ip=dict(required=True, type='str'),
shared_secret=dict(required=True, type='str'),
ike_version=dict(default=2, type='int'),
@ -288,7 +304,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind, fetch)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -297,6 +314,7 @@ def main():
else:
if state == 'present':
fetch = create(module, collection(module), kind)
labels_update(module, module.params, fetch)
changed = True
else:
fetch = {}
@ -311,9 +329,29 @@ def create(module, link, kind):
return wait_for_operation(module, auth.post(link, resource_to_request(module)))
def update(module, link, kind):
def update(module, link, kind, fetch):
update_fields(module, resource_to_request(module),
response_to_hash(module, fetch))
return fetch_resource(module, self_link(module), kind)
def update_fields(module, request, response):
if response.get('labels') != request.get('labels'):
labels_update(module, request, response)
def labels_update(module, request, response):
auth = GcpSession(module, 'compute')
return wait_for_operation(module, auth.put(link, resource_to_request(module)))
auth.post(
''.join([
"https://www.googleapis.com/compute/v1/",
"projects/{project}/regions/{region}/vpnTunnels/{name}/setLabels"
]).format(**module.params),
{
u'labels': module.params.get('labels'),
u'labelFingerprint': response.get('labelFingerprint')
}
)
def delete(module, link, kind):
@ -327,7 +365,7 @@ def resource_to_request(module):
u'name': module.params.get('name'),
u'description': module.params.get('description'),
u'targetVpnGateway': replace_resource_dict(module.params.get(u'target_vpn_gateway', {}), 'selfLink'),
u'router': module.params.get('router'),
u'router': replace_resource_dict(module.params.get(u'router', {}), 'selfLink'),
u'peerIp': module.params.get('peer_ip'),
u'sharedSecret': module.params.get('shared_secret'),
u'ikeVersion': module.params.get('ike_version'),
@ -343,9 +381,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'compute')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -356,9 +394,9 @@ def collection(module):
return "https://www.googleapis.com/compute/v1/projects/{project}/regions/{region}/vpnTunnels".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -373,8 +411,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result
@ -405,14 +441,15 @@ def response_to_hash(module, response):
u'name': response.get(u'name'),
u'description': module.params.get('description'),
u'targetVpnGateway': replace_resource_dict(module.params.get(u'target_vpn_gateway', {}), 'selfLink'),
u'router': module.params.get('router'),
u'router': replace_resource_dict(module.params.get(u'router', {}), 'selfLink'),
u'peerIp': response.get(u'peerIp'),
u'sharedSecret': response.get(u'sharedSecret'),
u'sharedSecretHash': response.get(u'sharedSecretHash'),
u'ikeVersion': response.get(u'ikeVersion'),
u'localTrafficSelector': response.get(u'localTrafficSelector'),
u'remoteTrafficSelector': response.get(u'remoteTrafficSelector'),
u'labels': response.get(u'labels')
u'labels': response.get(u'labels'),
u'labelFingerprint': response.get(u'labelFingerprint')
}

@ -61,7 +61,7 @@ EXAMPLES = '''
filters:
- name = test_object
project: test_project
auth_kind: service_account
auth_kind: serviceaccount
service_account_file: "/tmp/auth.pem"
'''
@ -71,7 +71,7 @@ items:
returned: always
type: complex
contains:
creation_timestamp:
creationTimestamp:
description:
- Creation timestamp in RFC3339 text format.
returned: success
@ -90,7 +90,7 @@ items:
- An optional description of this resource.
returned: success
type: str
target_vpn_gateway:
targetVpnGateway:
description:
- URL of the Target VPN gateway with which this VPN tunnel is associated.
returned: success
@ -99,30 +99,30 @@ items:
description:
- URL of router resource to be used for dynamic routing.
returned: success
type: str
peer_ip:
type: dict
peerIp:
description:
- IP address of the peer VPN gateway. Only IPv4 is supported.
returned: success
type: str
shared_secret:
sharedSecret:
description:
- Shared secret used to set the secure session between the Cloud VPN gateway and the
peer VPN gateway.
returned: success
type: str
shared_secret_hash:
sharedSecretHash:
description:
- Hash of the shared secret.
returned: success
type: str
ike_version:
ikeVersion:
description:
- IKE protocol version to use when establishing the VPN tunnel with peer VPN gateway.
- Acceptable IKE versions are 1 or 2. Default version is 2.
returned: success
type: int
local_traffic_selector:
localTrafficSelector:
description:
- Local traffic selector to use when establishing the VPN tunnel with peer VPN gateway.
The value should be a CIDR formatted string, for example `192.168.0.0/16`. The ranges
@ -130,7 +130,7 @@ items:
- Only IPv4 is supported.
returned: success
type: list
remote_traffic_selector:
remoteTrafficSelector:
description:
- Remote traffic selector to use when establishing the VPN tunnel with peer VPN gateway.
The value should be a CIDR formatted string, for example `192.168.0.0/16`. The ranges
@ -143,6 +143,12 @@ items:
- Labels to apply to this VpnTunnel.
returned: success
type: dict
labelFingerprint:
description:
- The fingerprint used for optimistic locking of this resource. Used internally during
updates.
returned: success
type: str
region:
description:
- The region where the tunnel is located.

@ -268,7 +268,7 @@ EXAMPLES = '''
disk_size_gb: 500
zone: us-central1-a
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
@ -286,7 +286,7 @@ RETURN = '''
- An optional description of this cluster.
returned: success
type: str
initial_node_count:
initialNodeCount:
description:
- The number of nodes to create in this cluster. You must ensure that your Compute
Engine resource quota is sufficient for this number of instances. You must also
@ -296,7 +296,7 @@ RETURN = '''
this and a nodePool at the same time.
returned: success
type: int
node_config:
nodeConfig:
description:
- Parameters used in creating the cluster's nodes.
- For requests, this field should only be used in lieu of a "nodePool" object, since
@ -307,19 +307,19 @@ RETURN = '''
returned: success
type: complex
contains:
machine_type:
machineType:
description:
- The name of a Google Compute Engine machine type (e.g.
- n1-standard-1). If unspecified, the default machine type is n1-standard-1.
returned: success
type: str
disk_size_gb:
diskSizeGb:
description:
- Size of the disk attached to each node, specified in GB. The smallest allowed disk
size is 10GB. If unspecified, the default disk size is 100GB.
returned: success
type: int
oauth_scopes:
oauthScopes:
description:
- The set of Google API scopes to be made available on all of the node VMs under the
"default" service account.
@ -332,7 +332,7 @@ RETURN = '''
enabled, in which case their required scopes will be added.
returned: success
type: list
service_account:
serviceAccount:
description:
- The Google Cloud Platform Service Account to be used by the node VMs. If no Service
Account is specified, the "default" service account is used.
@ -353,7 +353,7 @@ RETURN = '''
- 'Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }.'
returned: success
type: dict
image_type:
imageType:
description:
- The image type to use for this node. Note that for a given image type, the latest
version of it will be used.
@ -371,7 +371,7 @@ RETURN = '''
- 'Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }.'
returned: success
type: dict
local_ssd_count:
localSsdCount:
description:
- The number of local SSD disks to be attached to the node.
- 'The limit for this value is dependant upon the maximum number of disks available
@ -392,7 +392,7 @@ RETURN = '''
for more inforamtion about preemptible VM instances.'
returned: success
type: bool
master_auth:
masterAuth:
description:
- The authentication information for accessing the master endpoint.
returned: success
@ -409,23 +409,23 @@ RETURN = '''
the master endpoint is open to the Internet, you should create a strong password.
returned: success
type: str
cluster_ca_certificate:
clusterCaCertificate:
description:
- Base64-encoded public certificate that is the root of trust for the cluster.
returned: success
type: str
client_certificate:
clientCertificate:
description:
- Base64-encoded public certificate used by clients to authenticate to the cluster
endpoint.
returned: success
type: str
client_key:
clientKey:
description:
- Base64-encoded private key used by clients to authenticate to the cluster endpoint.
returned: success
type: str
logging_service:
loggingService:
description:
- 'The logging service the cluster should use to write logs. Currently available options: logging.googleapis.com
- the Google Cloud Logging service.'
@ -433,7 +433,7 @@ RETURN = '''
- if left as an empty string,logging.googleapis.com will be used.
returned: success
type: str
monitoring_service:
monitoringService:
description:
- The monitoring service the cluster should use to write metrics.
- 'Currently available options: monitoring.googleapis.com - the Google Cloud Monitoring
@ -450,20 +450,20 @@ RETURN = '''
resource.
returned: success
type: str
cluster_ipv4_cidr:
clusterIpv4Cidr:
description:
- The IP address range of the container pods in this cluster, in CIDR notation (e.g.
10.96.0.0/14). Leave blank to have one automatically chosen or specify a /14 block
in 10.0.0.0/8.
returned: success
type: str
addons_config:
addonsConfig:
description:
- Configurations for the various addons available to run in the cluster.
returned: success
type: complex
contains:
http_load_balancing:
httpLoadBalancing:
description:
- Configuration for the HTTP (L7) load balancing controller addon, which makes it
easy to set up HTTP load balancers for services in a cluster.
@ -476,7 +476,7 @@ RETURN = '''
it runs a small pod in the cluster that manages the load balancers.
returned: success
type: bool
horizontal_pod_autoscaling:
horizontalPodAutoscaling:
description:
- Configuration for the horizontal pod autoscaling feature, which increases or decreases
the number of replica pods a replication controller has based on the resource usage
@ -509,48 +509,48 @@ RETURN = '''
the masterAuth property of this resource for username and password information.
returned: success
type: str
initial_cluster_version:
initialClusterVersion:
description:
- The software version of the master endpoint and kubelets used in the cluster when
it was first created. The version can be upgraded over time.
returned: success
type: str
current_master_version:
currentMasterVersion:
description:
- The current software version of the master endpoint.
returned: success
type: str
current_node_version:
currentNodeVersion:
description:
- The current version of the node software components. If they are currently at multiple
versions because they're in the process of being upgraded, this reflects the minimum
version of all nodes.
returned: success
type: str
create_time:
createTime:
description:
- The time the cluster was created, in RFC3339 text format.
returned: success
type: str
node_ipv4_cidr_size:
nodeIpv4CidrSize:
description:
- The size of the address space on each node for hosting containers.
- This is provisioned from within the container_ipv4_cidr range.
returned: success
type: int
services_ipv4_cidr:
servicesIpv4Cidr:
description:
- The IP address range of the Kubernetes services in this cluster, in CIDR notation
(e.g. 1.2.3.4/29). Service addresses are typically put in the last /16 from the
container CIDR.
returned: success
type: str
current_node_count:
currentNodeCount:
description:
- The number of nodes currently in the cluster.
returned: success
type: int
expire_time:
expireTime:
description:
- The time the cluster will be automatically deleted in RFC3339 text format.
returned: success
@ -632,7 +632,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module))
update(module, self_link(module))
fetch = fetch_resource(module, self_link(module))
changed = True
else:
delete(module, self_link(module))
@ -689,9 +690,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link):
def fetch_resource(module, link, allow_not_found=True):
auth = GcpSession(module, 'container')
return return_if_object(module, auth.get(link))
return return_if_object(module, auth.get(link), allow_not_found)
def self_link(module):
@ -702,9 +703,9 @@ def collection(module):
return "https://container.googleapis.com/v1/projects/{project}/zones/{zone}/clusters".format(**module.params)
def return_if_object(module, response):
def return_if_object(module, response, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.

@ -198,6 +198,11 @@ options:
cluster:
description:
- The cluster this node pool belongs to.
- 'This field represents a link to a Cluster resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_container_cluster
task and then set this cluster field to "{{ name-of-resource }}" Alternatively,
you can set this cluster to a dictionary with the name key where the value is the
name of your Cluster.'
required: true
zone:
description:
@ -225,7 +230,7 @@ EXAMPLES = '''
cluster: "{{ cluster }}"
zone: us-central1-a
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
@ -242,19 +247,19 @@ RETURN = '''
returned: success
type: complex
contains:
machine_type:
machineType:
description:
- The name of a Google Compute Engine machine type (e.g.
- n1-standard-1). If unspecified, the default machine type is n1-standard-1.
returned: success
type: str
disk_size_gb:
diskSizeGb:
description:
- Size of the disk attached to each node, specified in GB. The smallest allowed disk
size is 10GB. If unspecified, the default disk size is 100GB.
returned: success
type: int
oauth_scopes:
oauthScopes:
description:
- The set of Google API scopes to be made available on all of the node VMs under the
"default" service account.
@ -267,7 +272,7 @@ RETURN = '''
enabled, in which case their required scopes will be added.
returned: success
type: list
service_account:
serviceAccount:
description:
- The Google Cloud Platform Service Account to be used by the node VMs. If no Service
Account is specified, the "default" service account is used.
@ -288,7 +293,7 @@ RETURN = '''
- 'Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }.'
returned: success
type: dict
image_type:
imageType:
description:
- The image type to use for this node. Note that for a given image type, the latest
version of it will be used.
@ -306,7 +311,7 @@ RETURN = '''
- 'Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }.'
returned: success
type: dict
local_ssd_count:
localSsdCount:
description:
- The number of local SSD disks to be attached to the node.
- 'The limit for this value is dependant upon the maximum number of disks available
@ -327,7 +332,7 @@ RETURN = '''
for more inforamtion about preemptible VM instances.'
returned: success
type: bool
initial_node_count:
initialNodeCount:
description:
- The initial node count for the pool. You must ensure that your Compute Engine resource
quota is sufficient for this number of instances. You must also have available firewall
@ -351,12 +356,12 @@ RETURN = '''
- Is autoscaling enabled for this node pool.
returned: success
type: bool
min_node_count:
minNodeCount:
description:
- Minimum number of nodes in the NodePool. Must be >= 1 and <= maxNodeCount.
returned: success
type: int
max_node_count:
maxNodeCount:
description:
- Maximum number of nodes in the NodePool. Must be >= minNodeCount.
- There has to enough quota to scale up the cluster.
@ -368,27 +373,27 @@ RETURN = '''
returned: success
type: complex
contains:
auto_upgrade:
autoUpgrade:
description:
- A flag that specifies whether node auto-upgrade is enabled for the node pool. If
enabled, node auto-upgrade helps keep the nodes in your node pool up to date with
the latest release version of Kubernetes.
returned: success
type: bool
auto_repair:
autoRepair:
description:
- A flag that specifies whether the node auto-repair is enabled for the node pool.
If enabled, the nodes in this node pool will be monitored and, if they fail health
checks too many times, an automatic repair action will be triggered.
returned: success
type: bool
upgrade_options:
upgradeOptions:
description:
- Specifies the Auto Upgrade knobs for the node pool.
returned: success
type: complex
contains:
auto_upgrade_start_time:
autoUpgradeStartTime:
description:
- This field is set when upgrades are about to commence with the approximate start
time for the upgrades, in RFC3339 text format.
@ -474,7 +479,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module))
update(module, self_link(module))
fetch = fetch_resource(module, self_link(module))
changed = True
else:
delete(module, self_link(module))
@ -524,9 +530,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link):
def fetch_resource(module, link, allow_not_found=True):
auth = GcpSession(module, 'container')
return return_if_object(module, auth.get(link))
return return_if_object(module, auth.get(link), allow_not_found)
def self_link(module):
@ -548,9 +554,9 @@ def collection(module):
return "https://container.googleapis.com/v1/projects/{project}/zones/{zone}/clusters/{cluster}/nodePools".format(**res)
def return_if_object(module, response):
def return_if_object(module, response, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.

@ -77,7 +77,7 @@ EXAMPLES = '''
dns_name: test.somewild2.example.com.
description: test zone
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
@ -89,7 +89,7 @@ RETURN = '''
user's convenience. Has no effect on the managed zone's function.
returned: success
type: str
dns_name:
dnsName:
description:
- The DNS name of this managed zone, for instance "example.com.".
returned: success
@ -105,20 +105,20 @@ RETURN = '''
- Must be unique within the project.
returned: success
type: str
name_servers:
nameServers:
description:
- Delegate your managed_zone to these virtual name servers; defined by the server
.
returned: success
type: list
name_server_set:
nameServerSet:
description:
- Optionally specifies the NameServerSet for this ManagedZone. A NameServerSet is
a set of DNS name servers that all host the same ManagedZones. Most users will leave
this field unset.
returned: success
type: list
creation_time:
creationTime:
description:
- The time that this resource was created on the server.
- This is in RFC3339 text format.
@ -163,7 +163,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -211,9 +212,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'dns')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -224,9 +225,9 @@ def collection(module):
return "https://www.googleapis.com/dns/v1/projects/{project}/managedZones".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -241,8 +242,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result

@ -71,6 +71,11 @@ options:
description:
- Identifies the managed zone addressed by this request.
- Can be the managed zone name or id.
- 'This field represents a link to a ManagedZone resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_dns_managed_zone
task and then set this managed_zone field to "{{ name-of-resource }}" Alternatively,
you can set this managed_zone to a dictionary with the name key where the value
is the name of your ManagedZone.'
required: true
extends_documentation_fragment: gcp
'''
@ -97,7 +102,7 @@ EXAMPLES = '''
- 10.1.2.3
- 40.5.6.7
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
@ -174,7 +179,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind, fetch)
update(module, self_link(module), kind, fetch)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind, fetch)
@ -238,9 +244,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'dns')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def fetch_wrapped_resource(module, kind, wrap_kind, wrap_path):
@ -269,17 +275,17 @@ def self_link(module):
return "https://www.googleapis.com/dns/v1/projects/{project}/managedZones/{managed_zone}/rrsets?name={name}&type={type}".format(**res)
def collection(module, extra_url=''):
def collection(module):
res = {
'project': module.params['project'],
'managed_zone': replace_resource_dict(module.params['managed_zone'], 'name')
}
return "https://www.googleapis.com/dns/v1/projects/{project}/managedZones/{managed_zone}/changes".format(**res) + extra_url
return "https://www.googleapis.com/dns/v1/projects/{project}/managedZones/{managed_zone}/changes".format(**res)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -294,8 +300,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result
@ -436,7 +440,7 @@ def wait_for_change_to_complete(change_id, module):
def get_change_status(change_id, module):
auth = GcpSession(module, 'dns')
link = collection(module, "/%s" % change_id)
link = collection(module) + "/%s" % change_id
return return_if_change_object(module, auth.get(link))['status']

@ -54,6 +54,11 @@ options:
topic:
description:
- A reference to a Topic resource.
- 'This field represents a link to a Topic resource in GCP. It can be specified in
two ways. You can add `register: name-of-resource` to a gcp_pubsub_topic task and
then set this topic field to "{{ name-of-resource }}" Alternatively, you can set
this topic to a dictionary with the name key where the value is the name of your
Topic.'
required: false
push_config:
description:
@ -105,7 +110,7 @@ EXAMPLES = '''
push_endpoint: https://myapp.graphite.cloudnativeapp.com/webhook/sub1
ack_deadline_seconds: 300
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
@ -121,7 +126,7 @@ RETURN = '''
- A reference to a Topic resource.
returned: success
type: dict
push_config:
pushConfig:
description:
- If push delivery is used with this subscription, this field is used to configure
it. An empty pushConfig signifies that the subscriber will pull and ack messages
@ -129,13 +134,13 @@ RETURN = '''
returned: success
type: complex
contains:
push_endpoint:
pushEndpoint:
description:
- A URL locating the endpoint to which messages should be pushed.
- For example, a Webhook endpoint might use "U(https://example.com/push".)
returned: success
type: str
ack_deadline_seconds:
ackDeadlineSeconds:
description:
- This value is the maximum time after a subscriber receives a message before the
subscriber should acknowledge the message. After message delivery but before the
@ -193,7 +198,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module))
update(module, self_link(module))
fetch = fetch_resource(module, self_link(module))
changed = True
else:
delete(module, self_link(module))
@ -241,9 +247,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link):
def fetch_resource(module, link, allow_not_found=True):
auth = GcpSession(module, 'pubsub')
return return_if_object(module, auth.get(link))
return return_if_object(module, auth.get(link), allow_not_found)
def self_link(module):
@ -254,9 +260,9 @@ def collection(module):
return "https://pubsub.googleapis.com/v1/projects/{project}/subscriptions".format(**module.params)
def return_if_object(module, response):
def return_if_object(module, response, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -319,7 +325,7 @@ def decode_request(response, module):
def encode_request(request, module):
request['topic'] = '/'.join(['projects', module.params['project'],
'topics', module.params['topic']])
'topics', module.params['topic']['name']])
request['name'] = '/'.join(['projects', module.params['project'],
'subscriptions', module.params['name']])

@ -58,7 +58,7 @@ EXAMPLES = '''
gcp_pubsub_topic:
name: test-topic1
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
@ -104,7 +104,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module))
update(module, self_link(module))
fetch = fetch_resource(module, self_link(module))
changed = True
else:
delete(module, self_link(module))
@ -150,9 +151,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link):
def fetch_resource(module, link, allow_not_found=True):
auth = GcpSession(module, 'pubsub')
return return_if_object(module, auth.get(link))
return return_if_object(module, auth.get(link), allow_not_found)
def self_link(module):
@ -163,9 +164,9 @@ def collection(module):
return "https://pubsub.googleapis.com/v1/projects/{project}/topics".format(**module.params)
def return_if_object(module, response):
def return_if_object(module, response, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.

@ -61,6 +61,11 @@ options:
instance:
description:
- The instance to create the database on.
- 'This field represents a link to a Instance resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_spanner_instance
task and then set this instance field to "{{ name-of-resource }}" Alternatively,
you can set this instance to a dictionary with the name key where the value is the
name of your Instance.'
required: true
extends_documentation_fragment: gcp
'''
@ -85,7 +90,7 @@ EXAMPLES = '''
name: webstore
instance: "{{ instance }}"
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
@ -98,7 +103,7 @@ RETURN = '''
The final segment of the name must be between 6 and 30 characters in length.
returned: success
type: str
extra_statements:
extraStatements:
description:
- 'An optional list of DDL statements to run inside the newly created database. Statements
can create tables, indexes, etc. These statements execute atomically with the creation
@ -147,7 +152,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module))
update(module, self_link(module))
fetch = fetch_resource(module, self_link(module))
changed = True
else:
delete(module, self_link(module))
@ -194,9 +200,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link):
def fetch_resource(module, link, allow_not_found=True):
auth = GcpSession(module, 'spanner')
return return_if_object(module, auth.get(link))
return return_if_object(module, auth.get(link), allow_not_found)
def self_link(module):
@ -216,9 +222,9 @@ def collection(module):
return "https://spanner.googleapis.com/v1/projects/{project}/instances/{instance}/databases".format(**res)
def return_if_object(module, response):
def return_if_object(module, response, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.

@ -99,7 +99,7 @@ EXAMPLES = '''
cost_center: ti-1700004
config: regional-us-central1
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
@ -117,13 +117,13 @@ RETURN = '''
- A reference to the instance configuration.
returned: success
type: str
display_name:
displayName:
description:
- The descriptive name for this instance as it appears in UIs. Must be unique per
project and between 4 and 30 characters in length.
returned: success
type: str
node_count:
nodeCount:
description:
- The number of nodes allocated to this instance.
returned: success
@ -189,7 +189,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module))
update(module, self_link(module))
fetch = fetch_resource(module, self_link(module))
changed = True
else:
delete(module, self_link(module))
@ -238,9 +239,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link):
def fetch_resource(module, link, allow_not_found=True):
auth = GcpSession(module, 'spanner')
return return_if_object(module, auth.get(link))
return return_if_object(module, auth.get(link), allow_not_found)
def self_link(module):
@ -251,9 +252,9 @@ def collection(module):
return "https://spanner.googleapis.com/v1/projects/{project}/instances".format(**module.params)
def return_if_object(module, response):
def return_if_object(module, response, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.

@ -62,6 +62,11 @@ options:
instance:
description:
- The name of the Cloud SQL instance. This does not include the project ID.
- 'This field represents a link to a Instance resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_sql_instance task
and then set this instance field to "{{ name-of-resource }}" Alternatively, you
can set this instance to a dictionary with the name key where the value is the name
of your Instance.'
required: true
extends_documentation_fragment: gcp
'''
@ -89,7 +94,7 @@ EXAMPLES = '''
charset: utf8
instance: "{{ instance }}"
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
@ -156,7 +161,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -204,9 +210,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'sql')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -226,7 +232,7 @@ def collection(module):
return "https://www.googleapis.com/sql/v1beta4/projects/{project}/instances/{instance}/databases".format(**res)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
return None

@ -246,6 +246,12 @@ options:
instances, this field determines whether the instance is Second Generation (recommended)
or First Generation.
required: false
settings_version:
description:
- The version of instance settings. This is a required field for update method to
make sure concurrent updates are handled properly. During update, use the most
recent settingsVersion value for this instance and do not try to update this value.
required: false
extends_documentation_fragment: gcp
'''
@ -261,25 +267,25 @@ EXAMPLES = '''
tier: db-n1-standard-1
region: us-central1
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
RETURN = '''
backend_type:
backendType:
description:
- "* FIRST_GEN: First Generation instance. MySQL only."
- "* SECOND_GEN: Second Generation instance or PostgreSQL instance."
- "* EXTERNAL: A database server that is not managed by Google."
returned: success
type: str
connection_name:
connectionName:
description:
- Connection name of the Cloud SQL instance used in connection strings.
returned: success
type: str
database_version:
databaseVersion:
description:
- The database engine type and version. For First Generation instances, can be MYSQL_5_5,
or MYSQL_5_6. For Second Generation instances, can be MYSQL_5_6 or MYSQL_5_7. Defaults
@ -288,7 +294,7 @@ RETURN = '''
after instance creation.'
returned: success
type: str
failover_replica:
failoverReplica:
description:
- The name and status of the failover replica. This property is applicable only to
Second Generation instances.
@ -309,7 +315,7 @@ RETURN = '''
property is applicable only to Second Generation instances.
returned: success
type: str
instance_type:
instanceType:
description:
- The instance type. This can be one of the following.
- "* CLOUD_SQL_INSTANCE: A Cloud SQL instance that is not replicating from a master."
@ -317,18 +323,18 @@ RETURN = '''
- "* READ_REPLICA_INSTANCE: A Cloud SQL instance configured as a read-replica."
returned: success
type: str
ip_addresses:
ipAddresses:
description:
- The assigned IP addresses for the instance.
returned: success
type: complex
contains:
ip_address:
ipAddress:
description:
- The IP address assigned.
returned: success
type: str
time_to_retire:
timeToRetire:
description:
- The due time for this IP to be retired in RFC 3339 format, for example 2012-11-15T16:19:00.094Z.
This field is only available when the IP is scheduled to be retired.
@ -341,18 +347,18 @@ RETURN = '''
from the instance, if supported.
returned: success
type: str
ipv6_address:
ipv6Address:
description:
- The IPv6 address assigned to the instance. This property is applicable only to First
Generation instances.
returned: success
type: str
master_instance_name:
masterInstanceName:
description:
- The name of the instance which will act as master in the replication setup.
returned: success
type: str
max_disk_size:
maxDiskSize:
description:
- The maximum disk size of the instance in bytes.
returned: success
@ -368,13 +374,13 @@ RETURN = '''
instance type (First Generation or Second Generation/PostgreSQL).
returned: success
type: str
replica_configuration:
replicaConfiguration:
description:
- Configuration specific to failover replicas and read replicas.
returned: success
type: complex
contains:
failover_target:
failoverTarget:
description:
- Specifies if the replica is the failover target. If the field is set to true the
replica will be designated as a failover replica.
@ -384,7 +390,7 @@ RETURN = '''
in different zone with the master instance.
returned: success
type: bool
mysql_replica_configuration:
mysqlReplicaConfiguration:
description:
- MySQL specific configuration when replicating from a MySQL on-premises master. Replication
configuration information such as the username, password, certificates, and keys
@ -394,28 +400,28 @@ RETURN = '''
returned: success
type: complex
contains:
ca_certificate:
caCertificate:
description:
- PEM representation of the trusted CA's x509 certificate.
returned: success
type: str
client_certificate:
clientCertificate:
description:
- PEM representation of the slave's x509 certificate .
returned: success
type: str
client_key:
clientKey:
description:
- PEM representation of the slave's private key. The corresponsing public key is encoded
in the client's asf asd certificate.
returned: success
type: str
connect_retry_interval:
connectRetryInterval:
description:
- Seconds to wait between connect retries. MySQL's default is 60 seconds.
returned: success
type: int
dump_file_path:
dumpFilePath:
description:
- Path to a SQL dump file in Google Cloud Storage from which the slave instance is
to be created. The URI is in the form gs://bucketName/fileName. Compressed gzip
@ -424,7 +430,7 @@ RETURN = '''
when using mysqldump.
returned: success
type: str
master_heartbeat_period:
masterHeartbeatPeriod:
description:
- Interval in milliseconds between replication heartbeats.
returned: success
@ -434,7 +440,7 @@ RETURN = '''
- The password for the replication connection.
returned: success
type: str
ssl_cipher:
sslCipher:
description:
- A list of permissible ciphers to use for SSL encryption.
returned: success
@ -444,18 +450,18 @@ RETURN = '''
- The username for the replication connection.
returned: success
type: str
verify_server_certificate:
verifyServerCertificate:
description:
- Whether or not to check the master's Common Name value in the certificate that it
sends during the SSL handshake.
returned: success
type: bool
replica_names:
replicaNames:
description:
- The replicas of the instance.
returned: success
type: list
service_account_email_address:
serviceAccountEmailAddress:
description:
- The service account email address assigned to the instance. This property is applicable
only to Second Generation instances.
@ -467,7 +473,7 @@ RETURN = '''
returned: success
type: complex
contains:
ip_configuration:
ipConfiguration:
description:
- The settings for IP Management. This allows to enable or disable the instance IP
and manage which external networks can connect to the instance. The IPv4 address
@ -475,19 +481,19 @@ RETURN = '''
returned: success
type: complex
contains:
ipv4_enabled:
ipv4Enabled:
description:
- Whether the instance should be assigned an IP address or not.
returned: success
type: bool
authorized_networks:
authorizedNetworks:
description:
- The list of external networks that are allowed to connect to the instance using
the IP. In CIDR notation, also known as 'slash' notation (e.g. 192.168.100.0/24).
returned: success
type: complex
contains:
expiration_time:
expirationTime:
description:
- The time when this access control entry expires in RFC 3339 format, for example
2012-11-15T16:19:00.094Z.
@ -505,7 +511,7 @@ RETURN = '''
or subnet here.
returned: success
type: str
require_ssl:
requireSsl:
description:
- Whether the mysqld should default to 'REQUIRE X509' for users connecting over IP.
returned: success
@ -517,6 +523,13 @@ RETURN = '''
or First Generation.
returned: success
type: str
settingsVersion:
description:
- The version of instance settings. This is a required field for update method to
make sure concurrent updates are handled properly. During update, use the most
recent settingsVersion value for this instance and do not try to update this value.
returned: success
type: int
'''
################################################################################
@ -578,7 +591,8 @@ def main():
)),
require_ssl=dict(type='bool')
)),
tier=dict(type='str')
tier=dict(type='str'),
settings_version=dict(type='int')
))
)
)
@ -595,7 +609,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind, fetch)
update(module, self_link(module), kind, fetch)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind, fetch)
@ -652,9 +667,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'sql')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -665,7 +680,7 @@ def collection(module):
return "https://www.googleapis.com/sql/v1beta4/projects/{project}/instances".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
return None
@ -895,13 +910,15 @@ class InstanceSettings(object):
def to_request(self):
return remove_nones_from_dict({
u'ipConfiguration': InstanceIpConfiguration(self.request.get('ip_configuration', {}), self.module).to_request(),
u'tier': self.request.get('tier')
u'tier': self.request.get('tier'),
u'settingsVersion': self.request.get('settings_version')
})
def from_response(self):
return remove_nones_from_dict({
u'ipConfiguration': InstanceIpConfiguration(self.request.get(u'ipConfiguration', {}), self.module).from_response(),
u'tier': self.request.get(u'tier')
u'tier': self.request.get(u'tier'),
u'settingsVersion': self.request.get(u'settingsVersion')
})

@ -59,6 +59,11 @@ options:
instance:
description:
- The name of the Cloud SQL instance. This does not include the project ID.
- 'This field represents a link to a Instance resource in GCP. It can be specified
in two ways. You can add `register: name-of-resource` to a gcp_sql_instance task
and then set this instance field to "{{ name-of-resource }}" Alternatively, you
can set this instance to a dictionary with the name key where the value is the name
of your Instance.'
required: true
password:
description:
@ -91,7 +96,7 @@ EXAMPLES = '''
password: secret-password
instance: "{{ instance }}"
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
@ -161,7 +166,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -231,9 +237,9 @@ def unwrap_resource(result, module):
return None
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'sql')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def fetch_wrapped_resource(module, kind, wrap_kind, wrap_path):
@ -270,7 +276,7 @@ def collection(module):
return "https://www.googleapis.com/sql/v1beta4/projects/{project}/instances/{instance}/users".format(**res)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
return None

@ -59,6 +59,11 @@ options:
bucket:
description:
- The name of the bucket.
- 'This field represents a link to a Bucket resource in GCP. It can be specified in
two ways. You can add `register: name-of-resource` to a gcp_storage_bucket task
and then set this bucket field to "{{ name-of-resource }}" Alternatively, you can
set this bucket to a dictionary with the name key where the value is the name of
your Bucket.'
required: true
domain:
description:
@ -139,6 +144,11 @@ options:
bucket:
description:
- The name of the bucket.
- 'This field represents a link to a Bucket resource in GCP. It can be specified in
two ways. You can add `register: name-of-resource` to a gcp_storage_bucket task
and then set this bucket field to "{{ name-of-resource }}" Alternatively, you can
set this bucket to a dictionary with the name key where the value is the name of
your Bucket.'
required: true
domain:
description:
@ -358,7 +368,7 @@ EXAMPLES = '''
gcp_storage_bucket:
name: ansible-storage-module
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
@ -396,7 +406,7 @@ RETURN = '''
entity would be domain-example.com.
returned: success
type: str
entity_id:
entityId:
description:
- The ID for the entity.
returned: success
@ -406,13 +416,13 @@ RETURN = '''
- The ID of the access-control entry.
returned: success
type: str
project_team:
projectTeam:
description:
- The project team associated with the entity.
returned: success
type: complex
contains:
project_number:
projectNumber:
description:
- The project team associated with the entity.
returned: success
@ -433,7 +443,7 @@ RETURN = '''
returned: success
type: complex
contains:
max_age_seconds:
maxAgeSeconds:
description:
- The value, in seconds, to return in the Access-Control-Max-Age header used in preflight
responses.
@ -451,13 +461,13 @@ RETURN = '''
- 'Note: "*" is permitted in the list of origins, and means "any Origin".'
returned: success
type: list
response_header:
responseHeader:
description:
- The list of HTTP headers other than the simple response headers to give permission
for the user-agent to share across domains.
returned: success
type: list
default_object_acl:
defaultObjectAcl:
description:
- Default access controls to apply to new objects when no ACL is provided.
returned: success
@ -489,7 +499,7 @@ RETURN = '''
entity would be domain-example.com.
returned: success
type: str
entity_id:
entityId:
description:
- The ID for the entity.
returned: success
@ -509,13 +519,13 @@ RETURN = '''
- The name of the object, if applied to an object.
returned: success
type: str
project_team:
projectTeam:
description:
- The project team associated with the entity.
returned: success
type: complex
contains:
project_number:
projectNumber:
description:
- The project team associated with the entity.
returned: success
@ -555,7 +565,7 @@ RETURN = '''
returned: success
type: complex
contains:
storage_class:
storageClass:
description:
- Target storage class. Required iff the type of the action is SetStorageClass.
returned: success
@ -571,32 +581,32 @@ RETURN = '''
returned: success
type: complex
contains:
age_days:
ageDays:
description:
- Age of an object (in days). This condition is satisfied when an object reaches the
specified age.
returned: success
type: int
created_before:
createdBefore:
description:
- A date in RFC 3339 format with only the date part (for instance, "2013-01-15").
This condition is satisfied when an object is created before midnight of the specified
date in UTC.
returned: success
type: str
is_live:
isLive:
description:
- Relevant only for versioned objects. If the value is true, this condition matches
live objects; if the value is false, it matches archived objects.
returned: success
type: bool
matches_storage_class:
matchesStorageClass:
description:
- Objects having any of the storage classes specified by this condition will be matched.
Values include MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, STANDARD, and DURABLE_REDUCED_AVAILABILITY.
returned: success
type: list
num_newer_versions:
numNewerVersions:
description:
- Relevant only for versioned objects. If the value is N, this condition is satisfied
when there are at least N versions (including the live version) newer than this
@ -617,12 +627,12 @@ RETURN = '''
returned: success
type: complex
contains:
log_bucket:
logBucket:
description:
- The destination bucket where the current bucket's logs should be placed.
returned: success
type: str
log_object_prefix:
logObjectPrefix:
description:
- A prefix for log object names.
returned: success
@ -648,17 +658,17 @@ RETURN = '''
- The entity, in the form project-owner-projectId.
returned: success
type: str
entity_id:
entityId:
description:
- The ID for the entity.
returned: success
type: str
project_number:
projectNumber:
description:
- The project number of the project the bucket belongs to.
returned: success
type: int
storage_class:
storageClass:
description:
- The bucket's default storage class, used whenever no storageClass is specified for
a newly-created object. This defines how objects in the bucket are stored and determines
@ -668,7 +678,7 @@ RETURN = '''
For more information, see storage classes.
returned: success
type: str
time_created:
timeCreated:
description:
- The creation time of the bucket in RFC 3339 format.
returned: success
@ -696,14 +706,14 @@ RETURN = '''
returned: success
type: complex
contains:
main_page_suffix:
mainPageSuffix:
description:
- If the requested object path is missing, the service will ensure the path has a
trailing '/', append this suffix, and attempt to retrieve the resulting object.
This allows the creation of index.html objects to represent directory pages.
returned: success
type: str
not_found_page:
notFoundPage:
description:
- If the requested object path is missing, and any mainPageSuffix object is missing,
if applicable, the service will return the named object from this bucket as the
@ -715,7 +725,7 @@ RETURN = '''
- A valid API project identifier.
returned: success
type: str
predefined_default_object_acl:
predefinedDefaultObjectAcl:
description:
- Apply a predefined set of default object access controls to this bucket.
- 'Acceptable values are: - "authenticatedRead": Object owner gets OWNER access,
@ -840,7 +850,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -899,9 +910,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'storage')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -912,9 +923,9 @@ def collection(module):
return "https://www.googleapis.com/storage/v1/b?project={project}".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -929,8 +940,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result

@ -58,6 +58,11 @@ options:
bucket:
description:
- The name of the bucket.
- 'This field represents a link to a Bucket resource in GCP. It can be specified in
two ways. You can add `register: name-of-resource` to a gcp_storage_bucket task
and then set this bucket field to "{{ name-of-resource }}" Alternatively, you can
set this bucket to a dictionary with the name key where the value is the name of
your Bucket.'
required: true
entity:
description:
@ -111,7 +116,7 @@ EXAMPLES = '''
entity: user-alexstephen@google.com
role: WRITER
project: "test_project"
auth_kind: "service_account"
auth_kind: "serviceaccount"
service_account_file: "/tmp/auth.pem"
state: present
'''
@ -143,7 +148,7 @@ RETURN = '''
entity would be domain-example.com.
returned: success
type: str
entity_id:
entityId:
description:
- The ID for the entity.
returned: success
@ -153,13 +158,13 @@ RETURN = '''
- The ID of the access-control entry.
returned: success
type: str
project_team:
projectTeam:
description:
- The project team associated with the entity.
returned: success
type: complex
contains:
project_number:
projectNumber:
description:
- The project team associated with the entity.
returned: success
@ -217,7 +222,8 @@ def main():
if fetch:
if state == 'present':
if is_different(module, fetch):
fetch = update(module, self_link(module), kind)
update(module, self_link(module), kind)
fetch = fetch_resource(module, self_link(module), kind)
changed = True
else:
delete(module, self_link(module), kind)
@ -267,9 +273,9 @@ def resource_to_request(module):
return return_vals
def fetch_resource(module, link, kind):
def fetch_resource(module, link, kind, allow_not_found=True):
auth = GcpSession(module, 'storage')
return return_if_object(module, auth.get(link), kind)
return return_if_object(module, auth.get(link), kind, allow_not_found)
def self_link(module):
@ -280,9 +286,9 @@ def collection(module):
return "https://www.googleapis.com/storage/v1/b/{bucket}/acl".format(**module.params)
def return_if_object(module, response, kind):
def return_if_object(module, response, kind, allow_not_found=False):
# If not found, return nothing.
if response.status_code == 404:
if allow_not_found and response.status_code == 404:
return None
# If no content, return nothing.
@ -297,8 +303,6 @@ def return_if_object(module, response, kind):
if navigate_hash(result, ['error', 'errors']):
module.fail_json(msg=navigate_hash(result, ['error', 'errors']))
if result['kind'] != kind:
module.fail_json(msg="Incorrect result: {kind}".format(**result))
return result

@ -53,7 +53,7 @@
gcp_container_node_pool_facts:
filters:
- name = {{ resource_name }}
cluster: {{ cluster }}
cluster: "{{ cluster }}"
zone: us-central1-a
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
@ -101,7 +101,7 @@
gcp_container_node_pool_facts:
filters:
- name = {{ resource_name }}
cluster: {{ cluster }}
cluster: "{{ cluster }}"
zone: us-central1-a
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"

@ -39,13 +39,18 @@
- result.changed == true
- "result.kind == 'dns#managedZone'"
- name: verify that managed_zone was created
shell: |
gcloud dns managed-zones describe --project="{{ gcp_project }}" "{{ resource_name }}"
gcp_dns_managed_zone_facts:
dns_name: test.somewild2.example.com.
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/ndev.clouddns.readwrite
register: results
- name: verify that command succeeded
assert:
that:
- results.rc == 0
- results['items'] | length == 1
# ----------------------------------------------------------------------------
- name: create a managed zone that already exists
gcp_dns_managed_zone:
@ -79,15 +84,18 @@
- result.changed == true
- result.has_key('kind') == False
- name: verify that managed_zone was deleted
shell: |
gcloud dns managed-zones describe --project="{{ gcp_project }}" "{{ resource_name }}"
gcp_dns_managed_zone_facts:
dns_name: test.somewild2.example.com.
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/ndev.clouddns.readwrite
register: results
failed_when: results.rc == 0
- name: verify that command succeeded
assert:
that:
- results.rc == 1
- "\"{{ resource_name }} was not found.\" in results.stderr"
- results['items'] | length == 0
# ----------------------------------------------------------------------------
- name: delete a managed zone that does not exist
gcp_dns_managed_zone:

@ -56,6 +56,19 @@
that:
- result.changed == true
- "result.kind == 'dns#resourceRecordSet'"
- name: verify that resource_record_set was created
gcp_dns_resource_record_set_facts:
managed_zone: "{{ managed_zone }}"
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/ndev.clouddns.readwrite
register: results
- name: verify that command succeeded
assert:
that:
- results['items'] | length >= 2
# ----------------------------------------------------------------------------
- name: create a resource record set that already exists
gcp_dns_resource_record_set:
@ -96,6 +109,19 @@
that:
- result.changed == true
- result.has_key('kind') == False
- name: verify that resource_record_set was deleted
gcp_dns_resource_record_set_facts:
managed_zone: "{{ managed_zone }}"
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/ndev.clouddns.readwrite
register: results
- name: verify that command succeeded
assert:
that:
- results['items'] | length >= 2
# ----------------------------------------------------------------------------
- name: delete a resource record set that does not exist
gcp_dns_resource_record_set:

@ -50,13 +50,17 @@
that:
- result.changed == true
- name: verify that subscription was created
shell: |
gcloud beta pubsub subscriptions list --project="{{ gcp_project}}" | grep "{{ resource_name }}" | grep 'test-topic1'
gcp_pubsub_subscription_facts:
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/pubsub
register: results
- name: verify that command succeeded
assert:
that:
- results.rc == 0
- results['items'] | length == 1
# ----------------------------------------------------------------------------
- name: create a subscription that already exists
gcp_pubsub_subscription:
@ -92,15 +96,17 @@
that:
- result.changed == true
- name: verify that subscription was deleted
shell: |
gcloud beta pubsub subscriptions list --project="{{ gcp_project}}" | grep "{{ resource_name }}" | grep 'test-topic1'
gcp_pubsub_subscription_facts:
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/pubsub
register: results
failed_when: results.rc == 0
- name: verify that command succeeded
assert:
that:
- results.rc == 1
- "\"{{ resource_name }} was not found.\" in results.stderr"
- results['items'] | length == 0
# ----------------------------------------------------------------------------
- name: delete a subscription that does not exist
gcp_pubsub_subscription:

@ -34,13 +34,17 @@
that:
- result.changed == true
- name: verify that topic was created
shell: |
gcloud beta pubsub topics list --project="{{ gcp_project}}"| grep 'topic: projects/.*/test-topic1'
gcp_pubsub_topic_facts:
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/pubsub
register: results
- name: verify that command succeeded
assert:
that:
- results.rc == 0
- results['items'] | length == 1
# ----------------------------------------------------------------------------
- name: create a topic that already exists
gcp_pubsub_topic:
@ -68,15 +72,17 @@
that:
- result.changed == true
- name: verify that topic was deleted
shell: |
gcloud beta pubsub topics list --project="{{ gcp_project}}"| grep 'topic: projects/.*/test-topic1'
gcp_pubsub_topic_facts:
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/pubsub
register: results
failed_when: results.rc == 0
- name: verify that command succeeded
assert:
that:
- results.rc == 1
- "\"{{ resource_name }} was not found.\" in results.stderr"
- results['items'] | length == 0
# ----------------------------------------------------------------------------
- name: delete a topic that does not exist
gcp_pubsub_topic:

@ -59,7 +59,7 @@
gcp_sql_user_facts:
filters:
- name = test-user
instance: {{ instance }}
instance: "{{ instance }}"
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
@ -108,7 +108,7 @@
gcp_sql_user_facts:
filters:
- name = test-user
instance: {{ instance }}
instance: "{{ instance }}"
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"

Loading…
Cancel
Save