Jenkins - Linux script - Extracting a variable from XML - linux

I have an XML file like shown below(XML response will be always same). I need to extract sessionToken value and use it in Jenkins file.
XML file -
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<XmlResponse><httpCode>200</httpCode><httpStatus>OK</httpStatus><action>None</action><messageLevel>INFO</messageLevel><objectsList>{"sessionToken":"1234567890"}</objectsList><results/></XmlResponse>
This is the code I tried in Jenkins and didn't work -
def var=sh([returnStdout: true, script: '`cat output.xml | cut -f10 -d"\\""`'])
println ("var is" + var)
Here is the output I see in Jenkins console log -
++cat output.xml
+ 1234567890 -----> session Token is extracted in this step but for some reason it assume this as command
/workspace/script.sh: line 1: 1234567890: command not found

Answer
Depending on the version of Jenkins you are running, pipe can be an issue. Please try the following solution
def var=sh([returnStdout: true, script:'/bin/bash -c \'`cat output.xml | cut -f10 -d"\\""`\''])

Related

parse error when trying to parse terraform output in GitHub Actions workflow with jq

I have a GitHub Actions workflow that reads output from a terraform configuration. I'm trying to do this:
terraform -chdir=terraform/live/dev output -json > /tmp/output.json
APP_URL=$(cat /tmp/output.json | jq -r '.app_url.value')
I'm getting the following error in the GitHub Action logs:
parse error: Invalid numeric literal at line 1, column 9
I added the following to debug this:
# debugging output.json file
echo "output.json:"
cat /tmp/output.json
And I'm finding that output of cat /tmp/output.json is:
/home/runner/work/_temp/2b622f60-be99-4a29-a295-593b06dde9a8/terraform-bin -chdir=terraform/live/dev output -json
{
"app_url": {
"sensitive": false,
"type": "string",
"value": "https://app.example.com"
}
}
This tells me that jq can't parse the temporary file that I wrote the terraform JSON output to because it seems to be adding the command to the file itself:
/home/runner/work/_temp/2b622f60-be99-4a29-a295-593b06dde9a8/terraform-bin -chdir=terraform/live/dev output -json
How can I get the terraform output as JSON and write it to a file without the extra header line that is causing the parse error?
When I run the same commands locally, I do not get this parse error.
Here's the code for the section of my GitHub Action workflow that is producing this error: https://github.com/briancaffey/django-step-by-step/blob/main/.github/workflows/terraform_frontend_update.yml#L72-L74
Things I have tried
using cd terraform/live/dev instead of -chdir=terraform/live/dev - this resulted in the same error
I was able to fix this issue by adding the following setting to the setup-terraform/#v1 action:
- uses: hashicorp/setup-terraform#v1
with:
terraform_version: 1.1.7
terraform_wrapper: false <-- added this
More documentation about this setting can be found here: https://github.com/hashicorp/setup-terraform#inputs
Whilst #briancaffey's answer is exactly right, if you need to use the terraform_wrapper for other parts of your workflow (e.g. using the output), you can switch out the problematic terraform calls with terraform-bin instead.
If you also want to run the script outside GitHub Actions, the following workaround will do the trick:
tf=terraform-bin
type "$tf" >/dev/null 2>&1 || tf=terraform
$tf output -json > /tmp/output.json
See https://github.com/hashicorp/setup-terraform/issues/167#issuecomment-1090760365 for an issue that mentions the same workaround.

How do I parse output from result of CURL command?

I have a Jenkins console output that looks like this:
Started by remote host 10.16.17.13
Building remotely on ep9infrajen201 (ep9) in workspace d:\Jenkins\workspace\Tools\Provision
[AWS-NetProvision] $ powershell.exe -NonInteractive -ExecutionPolicy ByPass "& 'C:\Users\user\AppData\Local\Temp\jenkins12345.ps1'"
Request network range: 10.1.0.0/13
{
    "networks":  [
                     "10.1.0.0/24"
                 ]
}
Finished: SUCCESS
I get this from a curl command that I run. to check the JENKINS_JOB_URL/lastBuild/consoleText
My question is, for the sake of some other automation I am doing, how do I get just "10.1.0.0/24" so I can assign it to a shell variable using LINUX tools?
Thank you
Since you listed jq among the tags of your duplicate question, I'll assume you have jq installed. You have to clean up your output to get JSON first, then get to the part of JSON you need. awk does the former, jq the latter.
.... | awk '/^{$/{p=1}{if(p){print}}/^}$/{p=0}' | jq -r .networks[0]
The AWK script looks for { on its own on a line to turn on a flag p; prints the current line if the flag is set; and switches off the flag when it encounters } all by itself.
EDIT: Since this output was generated on a DOS machine, it has DOS line endings (\r\n). To convert those before awk, additionally pipe through dos2unix.

How to sort strings.xml alphabetically in Android Studio

Hello is there a way to sort the string names alphabetically in strings.xml ?
It should sort it like this
Before
<string name="ccc">CText</string>
<string name="aaa">AText</string>
<string name="bbb">BText</string>
After
<string name="aaa">AText</string>
<string name="bbb">BText</string>
<string name="ccc">CText</string>
I am using Android Studio 1.5.1
I used AndroidXmlSorter plugin and it works perfectly for me.
How to install:
Go to Android Studio -> Preferences -> Plugins and hit Browse repositories..
Search for AndroidXmlSorter, install and restart your Android Studio. Go to your strings.xml file and hit Ctrl+L. Voila.
Disclaimer: I'm not the author of this plugin, I just found it by chance and I think all the credits should go to the plugin author. The repo is here: https://github.com/roana0229/android-xml-sorter
For anyone else who bumps into this. Copy all the string elements, paste into an Excel spreadsheet sort A-Z and then copy and paste back.
[Sort Android strings.xml in Alphabetical Order]
There is a plugin called Lines Sorter which can sort selected lines or whole files.
2022-09 | Simple plugin free solution:
Android studio includes option to sort lines / reverse lines.
Highlight lines of code to be sorted
unsorted lines
Edit > sort lines or Edit > reverse lines
sort line
Enjoy (reverse) alphabetical order
sorted lines
Sadly AndroidXmlSorter doesn't work for me when sorting multi-line strings.
My solution: Sort the strings.xml according to my android_strings_format.xslt (with xsltproc) and reformat it (with xmllint).
Cons: You have to execute a script. Therefore, it is not a true native feature of Android Studio. But you can easily execute scripts in Android Studio.
The script:
#!/bin/sh
sort_xml_file() {
xsltproc --output "$1" android_strings_format.xslt "$1"
export XMLLINT_INDENT=" "
xmllint --format --encode "utf-8" --output "$1" "$1"
}
sort_xml_file "src/main/res/values/strings.xml"
The android_strings_format.xslt file:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output
method="xml"
version="1.0"
encoding="UTF-8"
indent="yes"
omit-xml-declaration="yes"/>
<xsl:template match="/resources">
<resources>
<xsl:for-each select="string">
<xsl:sort select="#name"/>
<string name="{#name}">
<xsl:copy-of select="#* | node()"/>
</string>
</xsl:for-each>
</resources>
</xsl:template>
</xsl:stylesheet>
Works on Manjaro Linux x64.
EDIT: I have found a way to prevent multi-line text. I can enclose the text with quotes. <string name="available_version_error">"<u>ERRORa</u>"</string>
I used a XML formatter with an xslt definition - but this was too complex if you also uses plurals.
My solution: writing my own Python script:
import re
# add your files here
strings_files = ["path/to/strings.xml"]
# 1. transform the strings.xml file to a dict
# 2. sort the dict
# 3. transform the dict to a strings.xml file
def sort_strings_xml_file(path_to_file: str):
entries = dict()
current_entry_name = None
# read entries from strings.xml file
with open(path_to_file, "r") as file:
for line in file.readlines():
# a new entry was found in the strings.xml file
if line.strip().startswith("<string ") or line.strip().startswith("<plurals "):
current_entry_name = re.search(r'name="(.+)"', line).group(1)
entries[current_entry_name] = ""
# store content for the current entry
if current_entry_name is not None:
entries[current_entry_name] += line
# stop recording for the current entry
if line.strip().endswith("</string>") or line.strip().endswith("</plurals>"):
current_entry_name = None
entries = dict(sorted(entries.items()))
# write results back to the strings.xml file
with open(path_to_file, "w") as file:
file.write(('<?xml version="1.0" encoding="utf-8"?>'
'<resources>'
f'{"".join(entries.values())}</resources>'))
print(f"{path_to_file} was sorted")
for strings_file in strings_files:
sort_strings_xml_file(strings_file)
i would turn them to ASCII then sort that one and turn them back to string, very easy and very effective
Update: Easiest way is: Ctrl+A then Ctrl+Alt+L
For configuration: In Android studio, you can quickly sort XML code by following step:
Select all XML code in a file by Ctrl+A
Use combination: Ctrl+Alt+Shift+L
Select "Selected text" + "Rearrange code" Then Press RUN

How does "<<" operator work in linux shell?

I know the following code creates a file core-site.xml in the /opt/hadoop/conf directory. Can some one please break it down in linux shell terms for me? Especially the << operator & CORE_EOF? How does those markers work? I kind of understand this but wanted to know better.
cat >/opt/hadoop/conf/core-site.xml <<CORE_EOF
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>fs.default.name</name>
<value>hdfs://localhost:8020</value>
</property>
</configuration>
CORE_EOF
A command with the << operator will do the following things :
Launch the program specified in the left of the operator, cat for instance.
Grab user input, including newlines, until what is specified on the right of the operator is met on one line, EOF for instance
Send all that have been read except the EOF value to the standard input of the program on the left.
cat << EOF
Hello
World
EOF
Will send "Hello
World"
To the standard input of cat.
It is the same as doing this:
cat < file
With file containing :
Hello
World
Cat make a new file or rewrite old with same name in this condition
and put your string into file.
When you want to add strings into file
type this:
cat >> /opt/hadoop/conf/core-site.xml << EOF
String
String
EOF

While using sed command i receive the following error : Function cannot be parsed. Any Solutions or reason for this?

I need to replace a particular character in a text file with another character. For example, replacing "E" with "A":
Apple ice → ApplA Ica
While executing sed 's/E/A' < apple.txt > app.txt I receive the error
function cannot be parsed
Please help! I need to automate this using Antscript.
You should terminate your sed command with a slash (/) and I guess you want to exchange all occurences of E with A? Then you have to add a g for a global substitution:
sed 's/E/A/g' app.txt
sed 's/E/A/g' app.txt. You missed the trailing / (g means all occurrences),
Since you are in Ant environment, you probably don't need to execute sed at all, but rather use Copy task with filter, or ReplaceRegExp task.
<?xml version="1.0" encoding="UTF-8"?>
<project>
<replaceregexp file="apple.txt" flags="g" match="e" replace="A"/>
</project>
This alters the file in place:
$ cat apple.txt
Apple ice
$
$ ant
Buildfile: build.xml
BUILD SUCCESSFUL
Total time: 0 seconds
$
$ cat apple.txt
ApplA icA
Your example is strange with case (a|A, e|E). I'll assume that's typo.
Follow up: To declare encoding...
<?xml version="1.0" encoding="utf-8"?>
<project>
<replaceregexp file="apple.txt" encoding="utf-8" flags="g" match="Á" replace=" "/>
</project>
I tested this successfully. Before:
ApplA icA
ApplÁs icÁs
After:
ApplA icA
Appl s ic s

Resources