Hi,all! I am trying to apply two powershell script one by another after windows ec2 is initialized. But they arenot applied and no error during terraform execution like hitting 16 user_data constraint is shown. Just inside the ec2 user_data log can see it is not applied and user_data is empty. I will put a chunk of log on the end. So i guess the issue is in my code but not sure what i am doing wrong:
#User data template files web/app
data "cloudinit_config" "ec2_user_data" {
part {
filename = "common.ps1"
content_type = "text/x-shellscript"
content = <<-EOF
<persist>false</persist>
<powershell>
${templatefile("${path.module}/../scripts/common.ps1", {
computername = var.computername
})
}
</powershell>
EOF
}
part {
filename = "a.ps1"
content_type = "text/x-shellscript"
content = <<-EOF
<persist>false</persist>
<powershell>
${templatefile("${path.module}/../scripts/a.ps1", {
server_function = var.instance_function_id == "web" ? "web" : "app"
})
}
</powershell>
EOF
}
}
#User data template files sql
data "cloudinit_config" "ec2_user_data_sql" {
part {
filename = "common.ps1"
content_type = "text/x-shellscript"
content = <<-EOF
<persist>false</persist>
<powershell>
${templatefile("${path.module}/../scripts/common.ps1", {
computername = var.computername
})
}
</powershell>
EOF
}
part {
filename = "sql.ps1"
content_type = "text/x-shellscript"
content = <<-EOF
<persist>false</persist>
<powershell>
${templatefile("${path.module}/../scripts/sql.ps1", {
computername = var.computername
})
}
</powershell>
EOF
}
}
resource "aws_instance" "this" {
...
user_data = var.instance_function_id == "sql" ? data.cloudinit_config.ec2_user_data_sql.rendered : data.cloudinit_config.ec2_user_data.rendered
}
EC2Launch: C:\ProgramData\Amazon\EC2-Windows\Launch\Log\UserdataExecution.log
2022/10/19 12:40:59Z: Begin user data script process.
2022/10/19 12:41:00Z: Unable to parse <persist> tags. This can happen when tags are unmatched or poorly formed.
2022/10/19 12:41:00Z: Sending telemetry bool: IsUserDataScheduledPerBoot
2022/10/19 12:41:00Z: Unregister the scheduled task to persist user data.
2022/10/19 12:41:03Z: Unable to parse <runAsLocalSystem> tags. This can happen when tags are unmatched or poorly formed.
2022/10/19 12:41:03Z: Unable to parse <script> tags. This can happen when tags are unmatched or poorly formed.
2022/10/19 12:41:03Z: Unable to parse <powershell> tags. This can happen when tags are unmatched or poorly formed.
2022/10/19 12:41:03Z: Unable to parse <powershellArguments> tags. This can happen when tags are unmatched or poorly formed.
2022/10/19 12:41:03Z: User data script completed.
Hi @tahchiev,
From what you’ve shared it doesn’t seem like cloud-init is running on your Windows system, and I think that makes sense because cloud-init is typically for initializing Linux systems rather than Windows systems.
That means it isn’t appropriate to use the Cloud Init formats for your user_data
. Instead you should refer to the documentation of whatever AMI you are using to learn what software is configured to run on boot and parse the user data; you will need to provide that data in whatever format this software is expecting, which from the error message seems to be some kind of XML-based format.
Ok, but they why this code having only one script is working? If i try to call another after it i am hitting 16k user data limitation…if i decide to use s3 bucket to copy and transfer from it to windows and execute again is working but then in user data everyone can see the pass in clear text. That’s why i am trying to use templatefile…any other suggestions?
> user_data = "${ <<EOF
> <powershell>
> ${templatefile("${path.module}/../scripts/a.ps1", {
> computername = var.computername
>
> })
> }
> </powershell>
> <persist>false</persist>
> EOF
> }"
Hi @tahchiev,
To debug this will require understanding how user_data
works so you can see which piece of software is responsible for each part.
You can read the full details of how this works in the AWS documentation: Work with instance user data.
I will summarize that information here:
The EC2 API offers “user data” as just opaque raw data. EC2 itself doesn’t interpret the data at all, and instead just passes it verbatim to software installed in your AMI.
Terraform’s AWS provider in turn allows you to set a value for user_data
, but the AWS provider also doesn’t interpret the data at all and instead just passes it to the AWS API exactly as you provided it.
The AMI you have chosen will include some software configured to run at boot which retrieves the raw user data from the EC2 metadata API. That software then finally parses the data in some way that is entirely under that program’s control. That software decides what is valid input and what is invalid. That software decides how to react to valid input.
For many Linux distribution AMIs this special boot software is “cloud-init”, which supports a variety of different input formats, including the multipart MIME structure that the cloudinit_config
data source produces.
However, your AMI isn’t running cloud-init, and so sending cloud-init-style input to this other software is similar to trying to load a LibreOffice document into Microsoft Word: the data just isn’t in the right format that this software expects, and so it fails.
Your example without cloudinit_config
works presumably because in that case the data you provided is valid per the XML format this program is expecting.
Neither Terraform nor AWS have any involvement in interpreting this data other than just passing the raw bytes into the EC2 API so that your AMI can eventually parse it. To proceed you will need to learn the name of the software that is installed in your AMI to handle the user data and consult its documentation about what input formats are valid. You must then construct data that is in the syntax that this software expects.
You cannot send data in the format expected for one program (cloud-init) if that is not the software your AMI is running. The cloudinit_config
data source is useful only for AMIs which run cloud-init on startup.
1 Like