S3 module for downloading files is not working in ansible - amazon-web-services

This is the ansible code written for downloading files from S3 bucket "artefact-test".
- name: Download customization artifacts from S3
s3:
bucket: "artefact-test"
object: "cust/gitbranching.txt"
dest: "/home/ubuntu/"
mode: get
region: "{{ s3_region }}"
profile: "{{ s3_profile }}"
I have set the boto profile and aws profile too. I get different errors which i dont think are valid like -
failed: [127.0.0.1] => {"failed": true, "parsed": false}
Traceback (most recent call last):
File "/home/dmittal/.ansible/tmp/ansible-tmp-1462436903.77-107775915578620/s3", line 2320, in <module>
main()
File "/home/dmittal/.ansible/tmp/ansible-tmp-1462436903.77-107775915578620/s3", line 304, in main
ec2_url, aws_access_key, aws_secret_key, region = get_ec2_creds(module)
File "/home/dmittal/.ansible/tmp/ansible-tmp-1462436903.77-107775915578620/s3", line 2273, in get_ec2_creds
region, ec2_url, boto_params = get_aws_connection_info(module)
File "/home/dmittal/.ansible/tmp/ansible-tmp-1462436903.77-107775915578620/s3", line 2260, in get_aws_connection_info
if not boto_supports_profile_name():
File "/home/dmittal/.ansible/tmp/ansible-tmp-1462436903.77-107775915578620/s3", line 2191, in boto_supports_profile_name
return hasattr(boto.ec2.EC2Connection, 'profile_name')
AttributeError: 'module' object has no attribute 'ec2'
failed: [127.0.0.1] => {"failed": true}
msg: Target bucket cannot be found
failed: [127.0.0.1] => {"failed": true}
msg: Target key cannot be found
Whereas the bucket and key specified both exists on AWS.The same thing works if i use AWS-CLI commands to do the same.

There seems to have been a bug related to this. You might want to try adding the following import statement in the file ansible/module_utils/ec2.py -
import boto.ec2
Something like this - https://github.com/ansible/ansible/blob/9cf43ce17f20171b5740a6e0773f666cb47e2d5e/lib/ansible/module_utils/ec2.py#L31

Related

How to Use a Loop to Render Multiple Templates with multiple variables

I have a task to install monitoring agent in multiple hosts.
we are using three templates(yml files) during this installations. these template contain multiple tags. such as app name, teamdl, server IP, datacenter and so on...
for bulk installation we are using csv file which contains value for each tag.
Ask is to use each item in the csv file and use them as variable for all three templates.
I am able to read these items, but not able to use them. please support.
main.yml
- name: copy the csv file
copy:
src: "/u00/ansible/Playbooks/test.csv". # present in ansible controller
dest: "/u00/app/monitor/test.csv" #target server
become: yes
become_user: root
vars:
contents: "{{ lookup('file', '/u00/app/monitor/test.csv').split('\n') }}"
- name: Update config yml files
template: src={{item.src}} dest={{item.dest}}
loop:
- { src: '/u00/ansible/Playbooks/files/infra.yml_template', dest: '/u00/app/monitor/infra.yml' }
infra.yml_template -
custom_attributes:
application : {{ item.Application }}
env : {{ item.env }}
datacenter : {{ item.Datacenter }}
log:
file: /u00/app/monitor/infra.log
format: text
level: smart
forward: false
stdout: false
smart_level_entry_limit: 500
rotate:
max_size_mb: 100
max_files: 5
compression_enabled: true
file_pattern: rotated.YYYY-MM-DD_hh-mm-ss.log
error -
TASK [infra-integration : copy the csv file] ********************************
[0;32mok: [testserver1][0m
[0;32mok: [Testserver2][0m
TASK [Infra-integration : Update config yml files] **************************
[0;31mAn exception occurred during task execution. To see the full traceback, use -vvv. The error was: ansible.errors.AnsibleUndefinedVariable: 'dict object' has no attribute 'Application'[0m
[0;31mfailed: [testserver1] (item={'src': '/u00/ansible/Playbooks/files/infra.yml_template', 'dest': '/u00/app/monitor/infra.yml'}) => {"ansible_loop_var": "item", "changed": false, "item": {"dest": "/u00/app/monitor/infra.yml", "src": "/u00/ansible/Playbooks/files/infra.yml_template"}, "msg": "AnsibleUndefinedVariable: 'dict object' has no attribute 'Application'"}[0m
Expectation is to read csv file and use variables in three different template located at three different location.

Ansible inventory file in google cloud won't parse with any playbooks

My inventory file won't work for any of my playbooks I've tested it on multiple playbooks including ones that have worked for me in the past. I can't seem to figure out what's misconfigured or where the issue might be. The inventory file is fairly simple, and I have all of the requisites for getting ansible to run, ansible is up to date, and I'm positive the credentials file is fine since it's been working on my terraform configuration. Any input is appreciated!
Inventory file:
plugin: gcp_compute
projects:
- projectName
auth_kind: serviceaccount
service_account_file: /home/.../.config/gcloud/application_default_credentials.json
keyed_groups:
- prefix: gcp
key: labels
- prefix: tags
key: tags
Error that comes up when I try to use inventory:
config file = None
configured module search path = ['/home/.../.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/.../.local/lib/python3.10/site-packages/ansible
ansible collection location = /home/.../.ansible/collections:/usr/share/ansible/collections
executable location = /home/.../.local/bin/ansible-playbook
python version = 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0] (/usr/bin/python3)
jinja version = 3.0.3
libyaml = True
No config file found; using defaults
host_list declined parsing /home/.../inventory.gcp.yaml as it did not pass its verify_file() method
redirecting (type: inventory) ansible.builtin.gcp_compute to google.cloud.gcp_compute
Using inventory plugin 'ansible_collections.google.cloud.plugins.inventory.gcp_compute' to process inventory source '/home/.../inventory.gcp.yaml'
toml declined parsing /home/.../inventory.gcp.yaml as it did not pass its verify_file() method
[WARNING]: * Failed to parse /home/.../inventory.gcp.yaml with script plugin: problem running
/home/.../inventory.gcp.yaml --list ([Errno 8] Exec format error:
'/home/.../inventory.gcp.yaml')
File "/home/.../.local/lib/python3.10/site-packages/ansible/inventory/manager.py", line 293, in parse_source
plugin.parse(self._inventory, self._loader, source, cache=cache)
...
plugin.parse(self._inventory, self._loader, source, cache=cache)
File "/home/.../.local/lib/python3.10/site-packages/ansible/plugins/inventory/yaml.py", line 114, in parse
raise AnsibleParserError('Plugin configuration YAML file, not YAML inventory')
[WARNING]: * Failed to parse /home/.../inventory.gcp.yaml with ini plugin: Invalid host pattern
'plugin:' supplied, ending in ':' is not allowed, this character is reserved to provide a port.
File "/home/.../.local/lib/python3.10/site-packages/ansible/inventory/manager.py", line 293, in parse_source
plugin.parse(self._inventory, self._loader, source, cache=cache)
File "/home/.../.local/lib/python3.10/site-packages/ansible/plugins/inventory/ini.py", line 137, in parse
raise AnsibleParserError(e)
[WARNING]: Unable to parse /home/.../inventory.gcp.yaml as an inventory source
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit

Ansible AWS using a role_arn with ansible playbook not giving permissions

I have been stuck on this issue for days, and I can't seem to find anything around the exact same problem I've been having. Currently, I have credentials and config set up like so:
~/.aws/credentials
[default]
aws_access_key_id = ###########
aws_secret_access_key = ######################
[dev]
role_arn=arn:aws:iam::############:role/###AccessRole
source_profile=default
~/.aws/config
[default]
region = us-east-1
output = json
[profile dev]
role_arn = arn:aws:iam::############:role/###AccessRole
source_profile = default
When I run aws cli commands, everything runs fine. If I end up using AWS creds which have admin permissions, it works - but I can't do this in our system.
Currently, the default role can't access anything on purpose, it assumes the dev role. However, I can't get Ansible to recognise dev. I configured it all, and it works across Terraform, AWS CLI, Git. Currently, this is my input and error using ansible-playbook. I have removed certain info/linted the output below. As you can see, I'm using ec2.ini and ec2.py.
Has anyone come across this? Is it to do with using role_arn with Ansible? I have tried a plethora of things to get this to work, the state below is the current state of things.
Thanks in advance!
AWS_PROFILE=dev ansible-playbook -i ./inventory/ec2.py playbook.yml --private-key ###.pem
----
[WARNING]: * Failed to parse {home}/Ansible/Bastion/inventory/ec2.py with script
plugin: Inventory script ({home}/Ansible/Bastion/inventory/ec2.py) had an
execution error: Traceback (most recent call last): File
"{home}/Ansible/Bastion/inventory/ec2.py", line 1712, in <module>
Ec2Inventory() File "{home}Ansible/Bastion/inventory/ec2.py", line 285, in
__init__ self.do_api_calls_update_cache() File
"{home}/Ansible/Bastion/inventory/ec2.py", line 552, in do_api_calls_update_cache
self.get_instances_by_region(region) File
"{home}/Ansible/Bastion/inventory/ec2.py", line 608, in get_instances_by_region
conn = self.connect(region) File "{home}/Ansible/Bastion/inventory/ec2.py", line
570, in connect conn = self.connect_to_aws(ec2, region) File
"{home}/Ansible/Bastion/inventory/ec2.py", line 591, in connect_to_aws
sts_conn = sts.connect_to_region(region, **connect_args) File "{home}.local/lib/python2.7/site-
packages/boto/sts/__init__.py", line 51, in connect_to_region **kw_params) File
"{home}/.local/lib/python2.7/site-packages/boto/regioninfo.py", line 220, in connect return
region.connect(**kw_params) File "{home}/.local/lib/python2.7/site-packages/boto/regioninfo.py",
line 290, in connect return self.connection_cls(region=self, **kw_params) File
"{home}/.local/lib/python2.7/site-packages/boto/sts/connection.py", line 107, in __init__
provider=provider) File "{home}/.local/lib/python2.7/site-packages/boto/connection.py", line
1100, in __init__ provider=provider) File "{home}/.local/lib/python2.7/site-
packages/boto/connection.py", line 555, in __init__ profile_name) File
"{home}/.local/lib/python2.7/site-packages/boto/provider.py", line 201, in __init__
self.get_credentials(access_key, secret_key, security_token, profile_name) File
"{home}/.local/lib/python2.7/site-packages/boto/provider.py", line 297, in get_credentials
profile_name) boto.provider.ProfileNotFoundError: Profile "dev" not found!
[WARNING]: * Failed to parse {home}/Ansible/Bastion/inventory/ec2.py with ini
plugin: {home}/Ansible/Bastion/inventory/ec2.py:3: Error parsing host definition
''''': No closing quotation
[WARNING]: Unable to parse {home}/Ansible/Bastion/inventory/ec2.py as an inventory
source
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does
not match 'all'
PLAY [Create kp and access instance] *********************************************************
TASK [Setup variables] *************************************************************************************
ok: [localhost]
TASK [Backup previous key] *************************************************************************
changed: [localhost]
TASK [generate SSH key]
*******************************************************************
changed: [localhost]
TASK [Start and register instance] *****************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Profile given for AWS was not found. Please fix and retry."}
PLAY RECAP *************************************************************************************************
localhost : ok=3 changed=2 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
EDITS:
Name Value Type Location
---- ----- ---- --------
profile dev manual --profile
access_key ****************#### assume-role
secret_key ****************#### assume-role
region <not set> None None
{
"UserId": "<ACCESS_KEY?>:botocore-session-##########",
"Account": "############",
"Arn": "arn:aws:sts::############:assumed-role/###AccessRole/botocore-session-##########"
}
ec2.py is too old, it only use boto and can't work with roles. It is also deprecated, the correct way now to use aws dynamic inventory is to use aws_ec2 from the aws collection. It used boto3, support roles and is in the end more flexible. If needed, there is a compatiblity ec2.py config here, but it is recommended always to use the aws_ec2 groups and variables directly for the long run.
Check this link in github for the full story

EndpointConnectionError: Could not connect to the endpoint URL: "http://169.254.169.254/....."

I am trying to create AWS RDS and deploy lambda function using a python script. However, I am getting below error, looks like it is unable to communicate with the aws commands to create rds.
DEBUG: Caught retryable HTTP exception while making metadata service request to http://169.254.169.254/latest/meta-data/iam/security-credentials/: Could not connect to the endpoint URL: "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/botocore/utils.py", line 303, in _get_request
response = self._session.send(request.prepare())
File "/usr/lib/python2.7/site-packages/botocore/httpsession.py", line 282, in send raise EndpointConnectionError(endpoint_url=request.url, error=e)
EndpointConnectionError: Could not connect to the endpoint URL: "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
I am getting the aws credentials through SSO okta. In the ~/.aws directory,below are the contents of 'credentials' and 'config' file respectively.
[default]
aws_access_key_id = <Key Id>
aws_secret_access_key = <Secret Key>
aws_session_token = <Token>
[default]
region = us-west-2
```python
```
for az in availability_zones:
if aurora.get_db_instance(db_instance_identifier + "-" + az)[0] != 0:
aurora.create_db_instance(db_cluster_identifier, db_instance_identifier + "-" + az, az, subnet_group_identifier, db_instance_type)
else:
aurora.modify_db_instance(db_cluster_identifier, db_instance_identifier + "-" + az, az, db_instance_type)
# Wait for DB to become available for connection
iter_max = 15
iteration = 0
for az in availability_zones:
while aurora.get_db_instance(db_instance_identifier + "-" + az)[1]["DBInstances"][0]["DBInstanceStatus"] != "available":
iteration += 1
if iteration < iter_max:
logging.info("Waiting for DB instances to become available - iteration " + str(iteration) + " of " + str(iter_max))
time.sleep(10*iteration)
else:
raise Exception("Waiting for DB Instance to become available timed out!")
cluster_endpoint = aurora.get_db_cluster(db_cluster_identifier)[1]["DBClusters"][0]["Endpoint"]
The actual error below, coming from the while loop, DEBUG shows unable to locate credential, but the credential is there. I can deploy an Elastic Beanstalk environment from cli using the same aws credential, but not this. Looks like the above aurora.create_db_instance command failed.
DEBUG: Unable to locate credentials
Traceback (most recent call last):
File "./deploy_api.py", line 753, in <module> sync_rds()
File "./deploy_api.py", line 57, in sync_rds
while aurora.get_db_instance(db_instance_identifier + "-" + az)[1]["DBInstances"][0]["DBInstanceStatus"] != "available":
TypeError: 'NoneType' object has no attribute '__getitem__'
I had this error because an ECS task didn't have permissions to write to DynamoDB. The code causing the problem was:
from boto3 import resource
dynamodb_resource = resource("dynamodb")
The problem was resolved when I filled in the region_name, aws_access_key_id and aws_secret_access_key parameters for the resource() function call.
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html#boto3.session.Session.resource
If this doesn't solve your problem then check your code that connects to AWS services and make sure that you are filling in all of the proper function parameters.

GCP deploy instance fails from ansible script

I've been deploying clusters in GCP via ansible scripts for more then a year now, but all of a sudden one of my scripts keeps giving me this error:
libcloud.common.google.GoogleBaseError: u\"The zone 'projects/[project]/zones/europe-west1-d' does not have enough resources available to fulfill the request. Try a different zone, or try again later.
The obvious reason would be that I don't have enough resources, but not a whole lot has changed and quotas look good:
The ansible script itself doesn't ask for a lot.
I'm creating 3 instances of n1-standard-4 with 100GB SSD.
See snippet of script below:
tasks:
- name: create boot disks
gce_pd:
disk_type: pd-ssd
image: "debian-9-stretch-v20171025"
name: "{{ item.node }}-disk"
size_gb: 100
state: present
zone: "europe-west1-d"
service_account_email: "{{ service_account_email }}"
credentials_file: "{{ credentials_file }}"
project_id: "{{ project_id }}"
with_items: "{{nodes}}"
async: 3600
poll: 2
- name: create instances
gce:
instance_names: "{{item.node}}"
zone: "europe-west1-d"
machine_type: "n1-standard-4"
preemptible: "{{ false if item.num == '0' else true }}"
disk_auto_delete: true
disks:
- name: "{{ item.node }}-disk"
mode: READ_WRITE
state: present
service_account_email: "{{ service_account_email }}"
service_account_permissions: "compute-rw"
credentials_file: "{{ credentials_file }}"
project_id: "{{ project_id }}"
tags: "elasticsearch"
register: gce_raw_results
with_items: "{{nodes}}"
async: 3600
poll: 2
Update 1:
The service account is editor of the entire project. So right issue seems unlikely.
It started happening March 24 2018. And every night since then. So if it's a 'out of stock' issue that would be very coincidental, right?
Besides I have been running this script the entire day so far and it fails most of the time (see below for success).
I've tested a few times and it might have something to do with the 'preemptible' flag on the instance. (I start 3 nodes, but at least the first has to stay up to at least work) => preemptible: "{{ false if item.num == '0' else true }}"
If I turn off preemptible (false) then it runs without a hitch.
The 'workaround' seems to be just don't use preemptible instances, but this used to work for a year without failing once. Did something change?
Did GCP's API change? Did ansible gce not implement these changes?
The full error is:
TASK [Gathering Facts]
****************************************************************************************************************************************************************************************************************************************************************************************************** ok: [localhost]
TASK [create boot disks]
**************************************************************************************************************************************************************************************************************************************************************************************************** changed: [localhost] => (item={u'node': u'elasticsearch-link-0',
u'ip_field': u'private_ip', u'zone': u'europe-west1-d',
u'cluster_name': u'elasticsearch-link', u'num': u'0', u'machine_type':
u'n1-standard-4', u'project_id': u'[projectid]'}) changed: [localhost]
=> (item={u'node': u'elasticsearch-link-1', u'ip_field': u'private_ip', u'zone': u'europe-west1-d', u'cluster_name':
u'elasticsearch-link', u'num': u'1', u'machine_type':
u'n1-standard-4', u'project_id': u'[projectid]'}) ok: [localhost] =>
(item={u'node': u'elasticsearch-link-2', u'ip_field': u'private_ip',
u'zone': u'europe-west1-d', u'cluster_name': u'elasticsearch-link',
u'num': u'2', u'machine_type': u'n1-standard-4', u'project_id':
u'[projectid]'})
TASK [create instances]
***************************************************************************************************************************************************************************************************************************************************************************************************** changed: [localhost] => (item={u'node': u'elasticsearch-link-0',
u'ip_field': u'private_ip', u'zone': u'europe-west1-d',
u'cluster_name': u'elasticsearch-link', u'num': u'0', u'machine_type':
u'n1-standard-4', u'project_id': u'[projectid]'}) changed: [localhost]
=> (item={u'node': u'elasticsearch-link-1', u'ip_field': u'private_ip', u'zone': u'europe-west1-d', u'cluster_name':
u'elasticsearch-link', u'num': u'1', u'machine_type':
u'n1-standard-4', u'project_id': u'[projectid]'}) failed: [localhost]
(item={u'node': u'elasticsearch-link-2', u'ip_field': u'private_ip',
u'zone': u'europe-west1-d', u'cluster_name': u'elasticsearch-link',
u'num': u'2', u'machine_type': u'n1-standard-4', u'project_id':
u'[projectid]'}) => {"ansible_job_id": "371957735383.2688",
"changed": false, "cmd":
"/tmp/.ansible-airflow/ansible-tmp-1522742180.0-71790706749341/gce.py",
"data": "", "failed": 1, "finished": 1, "item": {"cluster_name":
"elasticsearch-link", "ip_field": "private_ip", "machine_type":
"n1-standard-4", "node": "elasticsearch-link-2", "num": "2",
"project_id": "[projectid]", "zone": "europe-west1-d"}, "msg":
"Traceback (most recent call last):\n File
\"/tmp/.ansible-airflow/ansible-tmp-1522742180.0-71790706749341/async_wrapper.py\",
line 158, in _run_module\n (filtered_outdata, json_warnings) =
_filter_non_json_lines(outdata)\n File \"/tmp/.ansible-airflow/ansible-tmp-1522742180.0-71790706749341/async_wrapper.py\",
line 99, in _filter_non_json_lines\n raise ValueError('No start of
json char found')\nValueError: No start of json char found\n",
"stderr": "Traceback (most recent call last):\n File
\"/tmp/ansible_OnIK1e/ansible_module_gce.py\", line 750, in \n
main()\n File \"/tmp/ansible_OnIK1e/ansible_module_gce.py\", line
712, in main\n module, gce, inames, number)\n File
\"/tmp/ansible_OnIK1e/ansible_module_gce.py\", line 524, in
create_instances\n instance, lc_machine_type, lc_image(),
**gce_args\n File \"/usr/local/lib/python2.7/dist-packages/libcloud/compute/drivers/gce.py\",
line 3874, in create_node\n self.connection.async_request(request,
method='POST', data=node_data)\n File
\"/usr/local/lib/python2.7/dist-packages/libcloud/common/base.py\",
line 784, in async_request\n response = request(**kwargs)\n File
\"/usr/local/lib/python2.7/dist-packages/libcloud/compute/drivers/gce.py\",
line 121, in request\n response = super(GCEConnection,
self).request(*args, **kwargs)\n File
\"/usr/local/lib/python2.7/dist-packages/libcloud/common/google.py\",
line 806, in request\n *args, **kwargs)\n File
\"/usr/local/lib/python2.7/dist-packages/libcloud/common/base.py\",
line 641, in request\n response = responseCls(**kwargs)\n File
\"/usr/local/lib/python2.7/dist-packages/libcloud/common/base.py\",
line 163, in init\n self.object = self.parse_body()\n File
\"/usr/local/lib/python2.7/dist-packages/libcloud/common/google.py\",
line 268, in parse_body\n raise GoogleBaseError(message,
self.status, code)\nlibcloud.common.google.GoogleBaseError: u\"The
zone 'projects/[projectid]/zones/europe-west1-d' does not have enough
resources available to fulfill the request. Try a different zone, or
try again later.\"\n", "stderr_lines": ["Traceback (most recent call
last):", " File \"/tmp/ansible_OnIK1e/ansible_module_gce.py\", line
750, in ", " main()", " File
\"/tmp/ansible_OnIK1e/ansible_module_gce.py\", line 712, in main", "
module, gce, inames, number)", " File
\"/tmp/ansible_OnIK1e/ansible_module_gce.py\", line 524, in
create_instances", " instance, lc_machine_type, lc_image(),
**gce_args", " File \"/usr/local/lib/python2.7/dist-packages/libcloud/compute/drivers/gce.py\",
line 3874, in create_node", "
self.connection.async_request(request, method='POST',
data=node_data)", " File
\"/usr/local/lib/python2.7/dist-packages/libcloud/common/base.py\",
line 784, in async_request", " response = request(**kwargs)", "
File
\"/usr/local/lib/python2.7/dist-packages/libcloud/compute/drivers/gce.py\",
line 121, in request", " response = super(GCEConnection,
self).request(*args, **kwargs)", " File
\"/usr/local/lib/python2.7/dist-packages/libcloud/common/google.py\",
line 806, in request", " *args, **kwargs)", " File
\"/usr/local/lib/python2.7/dist-packages/libcloud/common/base.py\",
line 641, in request", " response = responseCls(**kwargs)", " File
\"/usr/local/lib/python2.7/dist-packages/libcloud/common/base.py\",
line 163, in init", " self.object = self.parse_body()", " File
\"/usr/local/lib/python2.7/dist-packages/libcloud/common/google.py\",
line 268, in parse_body", " raise GoogleBaseError(message,
self.status, code)", "libcloud.common.google.GoogleBaseError: u\"The
zone 'projects/[projectid]/zones/europe-west1-d' does not have enough
resources available to fulfill the request. Try a different zone, or
try again later.\""]}
to retry, use: --limit #/usr/local/airflow/ansible/playbooks/elasticsearch-link-cluster-create.retry
The error message is not showing that is an error with the quota, but rather an issue with the zone resources, I would advise you to try a new zone.
Quoting from the documentation:
Even if you have a regional quota, it is possible that a resource might not be available in a specific zone. For example, you might have quota in region us-central1 to create VM instances, but might not be able to create VM instances in the zone us-central1-a if the zone is depleted. In such cases, try creating the same resource in another zone, such as us-central1-f.
Therefore when creating the script you should take this possibility into account even if it is not so common.
This issue is even more highlithed in case of preentible instances since:
Preemptible instances are finite Compute Engine resources, so they might not always be available. [...] these instances if it requires access to those resources for other tasks. Preemptible instances are excess Compute Engine capacity so their availability varies with usage.
UPDATE
To doublecheck what I am saying you can try to keep the preentible flag and change the zone to be sure the script it is working properly and it is a stockout happening during the evening (and since during the day it works this should be the case).
If the issue it is really the availability -| you might consider to spin up preentible instance and if not available, catch the error and then either rely on normal one or on a different zone |-
UPDATE2
As I promised I created on your behalf the feature request, you can follow the updates on the public tracker.
I advise you to start it in order to receive the updates on the email:
https://issuetracker.google.com/77734062