Multi match in re2 regex for terraform - regex

I'm trying to apply regex in something like this, in terraform.
variable "version" {
type = "string"
default = https://s3-us-east-1.amazonaws.com/bucket/folder/item-v1.2/item-item2-v1.2.gz
description = "version"
}
name = "${replace(var.version, "//", "")}"
I just need to replace everything and output only "v1.2" for the name, specifically from the item-v1.2 file path. I was thinking of doing something along the lines of
name = "${replace(var.version, "//", "")}"
wherein I replace everything but v1.2.
Any idea how to do it? Thank you in advance!

There are a couple of issues with your variable definition (e.g. wrong use of quotes, variable name "version" is reserved due to its special meaning inside module blocks, and so on) so I operate on the following:
variable "my_version" {
type = string
default = "https://s3-us-east-1.amazonaws.com/bucket/folder/item-v1.2/item-item2-v1.2.gz"
description = "version"
}
Then you can extract the version (or replace everything else except the version as requested) from the sub-folder path like this (this has been run and tested with terraform console):
$ terraform console
> var.my_version
"https://s3-us-east-1.amazonaws.com/bucket/folder/item-v1.2/item-item2-v1.2.gz"
> regex(".*-(.*)/.*.gz", var.my_version)[0]
"v1.2"
> replace(var.my_version, "/.*-(.*)/.*.gz/", "<before> $1 <after>")
"<before> v1.2 <after>"

Related

Terraform - Check If Variable Ends With String & Remove

We've set up our TF GKE code so that the user can specify either the region or zone for the cluster.
However, we need to then check this variable and remove the zone suffix (if it exists) for the deployment of static IP addresses.
We have the following variable:
variable "k8s_cluster_location" {
type = string
default = "europe-west2"
validation {
condition = contains(["europe-west2", "europe-west2-a", "europe-west2-b", "europe-west2-c", "us-east4", "us-east4-a", "us-east4-b", "us-east4-c", "europe-west1", "europe-west1-a", "europe-west1-b", "europe-west1-c" ], var.k8s_cluster_location)
error_message = "Given GCP location not (yet) supported. Contact X if you think it should..."
}
description = "Location of the Kubernetes cluster."
}
If, for example, the variable is "europe-west2-a", we need to remove "-a" to acquire the parent region.
Would we need to incorporate a Regex check? Or could we use something like StartsWith()/EndsWith()?
I would definitely recommend the regular expression solution here as you suggest:
variable "k8s_cluster_location" {
type = string
default = "europe-west2"
validation {
condition = can(regex("(?:europe-west[12])|(?:us-east4)", var.k8s_cluster_location))
error_message = "Given GCP location not (yet) supported. Contact X if you think it should..."
}
description = "Location of the Kubernetes cluster."
}
Note that if you are using Terraform 1.3.x, then you can also use the var.k8s_cluster_location value in the error_message instead of "Given GCP location".
For your other suggestion of startswith(), you would need to do something like anytrue(startswith(var.k8s_cluster_location, "europe-west1"), startswith(var.k8s_cluster_location, "europe-west2"), startswith(var.k8s_cluster_location, "us-east4")), but that feels slightly messier to me.

Visual Studio Snippet: Can I use TM_FILENAME to get a namespace from RELATIVE_FILEPATH?

I am toying with Visual Studio Snippets for a while now, and wonder if/how I can use TM_FILENAME to get a namespace from RELATIVE_FILEPATH. For example, I have:
RELATIVE_FILEPATH = src\model\RegisterModel.php
TM_FILENAME = RegisterModel.php
I want to strip the latter from the first, and the last \ as well, so I will end up with src\model
I can get it working if I use RegisterModel.php as a string, but not if I use TM_FILENAME as a variable. Is that even possible?
This is what works: ${RELATIVE_FILEPATH/(RegisterModel.php)//gi}
But I want something like this: ${RELATIVE_FILEPATH/(TM_FILENAME )//gi}
Thanks in advance!
This will get you what you want:
"filepath": {
"prefix": "rfp",
"body": [
"${RELATIVE_FILEPATH/(\\\\[^\\\\]*)$//i}", // with lots of escapes
],
"description": "directories of current file"
}
${RELATIVE_FILEPATH/${TM_FILENAME}//gi} will not work as according to the grammar only a regex can go into that ${TM_FILENAME} spot in the transform. See snippet grammar.
Relevant part of the grammar: transform ::= '/' regex '/' (format | text)+ '/' options
${RELATIVE_FILEPATH/[${TM_FILENAME}]//gi} results in:
src\od\Rgsrod.php because [${TM_FILENAME}] is treated as a regex (just a alternate list of those characters literally) and so each of those characters is removed from the RELATIVE_FILEPATH.
This is what I was trying to create. This snippet creates a php class template with the proper class name and namespace from the file name and location.
So, snippet
"php class": {
"prefix": "_pclass",
"body": "<?php\n\nnamespace app\\\\${RELATIVE_FILEPATH/(\\\\[^\\\\]*)$//i};\n\nclass $TM_FILENAME_BASE{\n\n\tpublic function __construct(){}\n\n\tpublic function $1($2){\n\n\t\t$3\n\t}\n}",
"description": "PHP class"
}
called in I:\xampp\htdocs\mvc2\src\core\form\Field.php creates
<?php
namespace app\src\core\form;
class Field{
public function __construct(){}
public function (){
}
}
with the cursor on the method name. Saves me quite a bit of time, hope it's just as helpful for others.

How to convert json property names from snake to camel case

I have a json document like so... and I'm trying to convert the property names (not values) from snake case to camel.
ex -
message_type_id to messageTypeId
and _id to id
and point_altitude to pointAltitude
{
"#version": "1",
"point_altitude": 530,
"_id": "3325",
"header": {
"raw_message": "",
"message_type_id": "ping_event"
}
}
I've tried find ((\w)[_]{1,1}([a-z]{1,1})) and replace $1\U$2
but that also changes the values as well. I've also tried using positive lookaheads by adding .+?(?=\:) to the end of the find but that stops finding any second underscores in the property names.
https://regex101.com/r/jK5mP3/14
Doing this with a single regex replace is possible but probably not the best choice. Try
(?<=[\w])(?:_([a-z]))([^_"]*+)(?!"\s)|"_([a-z]+)"
Demo
I would rather suggest parsing the JSON and simply iterate of the property names. Depending on your environment, you could use code or a library like camelize or a command-line tool like jd (e.g. this jd answer deals with a similar problem).

regex ansible lineinfile subsection

I am fairly new to ansible and have been solving the following problem with a shell script, but the proper way I believe is to use the lineinfile module, just not sure how to accomplish this.
Let's say I have a file with the following text in it.
<cpu>
<alarm>
active = yes
</alarm>
</cpu>
<disk>
<alarm>
active = yes
<fixed>
<#>
active = yes
description = File system /
<inode_error>
active = yes
threshold = 2
message = InodeError
</inode_error>
</#>
<#boot>
active = yes
description = File system /boot
percent = yes
<error>
active = yes
threshold = 5
message = DiskError
</error>
</#boot>
</fixed>
</alarm>
</disk>
I want to make sure the following section is set correctly.
<disk><alarm><fixed><#boot><error>"threshold = 2"</error></#boot></fixed></alarm></disk>
is there a way to only (modify/make sure exists) that line, normally this file is much larger with many more sections, but I erased some so the question is readable.
Update: Modifying this as it is not valid XML and the XML module will not parse the file correctly.
Thanks!
lineinfile scans file per line, so you can't define complex multiline regexp for context definition.
replace module support multiline regexp.
If you have threshold = X in the file and want to be sure it is set to specific value, you can use this regexp:
- replace:
path: ./test.txt
regexp: '(<disk>[\s\S]*<alarm>[\s\S]*<#boot>[\s\S]*<error>[\s\S]*)(threshold\s*=\s*\d+)([\s\S]*?<\/error>)'
replace: '\1threshold = 2\3'
It searches for line threshold\s*=\s*\d+ inside <disk>...<alarm>...<#boot>...<error>....
This code is idempotent – so if threshold = 2, then nothing is done.
But if there is no threshold = X string, it will fail. You should construct more complex regular expression for that case.
you could use the lineinfile module (http://docs.ansible.com/ansible/latest/lineinfile_module.html) where you could write a regex to modify/add the line and use the validate function to run a command to ensure that the xml file has the proper syntax.
If you are on Ansible 2.4 you can use the xml module (https://docs.ansible.com/ansible/2.4/xml_module.html) and use the attribute parameter to check if the xpath in xml file is set, like that:
- name: Read attribute value
xml:
path: /foo/bar.xml
xpath: /business/website/validxhtml
content: attribute
attribute: validatedon
register: xmlresp
regards

Regex for everything but partial substring

I'm usually pretty good with regex but this one has me stumped. I've read the other SO posts about negative looks but nothing seemed to work. I'm looking for a pure regex solution (not piped through anything like grep) because this has to be a single operation (in Atom IDE search).
Here's the issue:
Looking for all instances of the word "core" that are NOT preceded by "vpc_" and specifically capturing "core", not lines that contain core, because this is for Find/Replace, so I don't want to "select" the whole line, just the word core.
EDIT:
resource "aws_internet_gateway" "igw_core" {
vpc_id = "${aws_vpc.vpc_core.id}"
tags {
Environment = "${var.environment}"
Name = "${var.environment}_igw_core"
Version = "${var.version}"
}
}
I want to replace "core" with "foo" except "vpc_core" which should remain. The result should be:
resource "aws_internet_gateway" "igw_foo" {
vpc_id = "${aws_vpc.vpc_core.id}"
tags {
Environment = "${var.environment}"
Name = "${var.environment}_igw_foo"
Version = "${var.version}"
}
}