sed not finding file when using a pattern through ansible - sed

I have the following role:
---
- name: Replaces a string in a file
command: sed 's/'"{{ target_string }}"'/'"{{ new_string }}"'/g' -i {{ target_file_name }}
chdir="{{ target_file_location }}"
Which is called as follows:
- { role: string_replace_in_file, target_string: "localhost", new_string: "{{ myValue }}", target_file_name: "*.scripts.js", target_file_location: "/path/to/folder" }
The file i want to modify is aea342.scripts.js
I get the following output:
failed: [myMachine] => {"changed": true, "cmd": ["sed", "s/localhost/myValue/g", "-i", ".*.scripts.js"], "delta": "0:00:00.031107", "end": "2016-02-02 14:26:21.715652", "rc": 2, "start": "2016-02-02 14:26:21.684545", "warnings": ["Consider using template or lineinfile module rather than running sed"]}
stderr: sed: can't read .*.scripts.js: No such file or directory
When I run sed 's/localhost/myValue/g' -i *.scripts.js manually on my machine however it works.

Bruce is correct. Use shell to expand globs. I didn't test this. Can you try:
- name: Replaces a string in a file
shell: sed -i "s/<search>/<replace>/g" target_file_location/target_file_name(s)

From the Ansible documentation on the command module:
It will not be processed through the shell, so variables like $HOME and operations like "<", ">", "|", and "&" will not work
This also means that globs like "*.scripts.js" won't be expanded when you use the command module. If you need to use "*" then you should switch to using the shell module. As its name implies, it does run through a command shell so things like "*" will be properly expanded.

Related

etc/kubernetes/admin.conf didn't created - kubespray

I want to install the new cluster on 3 machines.
I ran this command:
ansible-playbook -i inventory/local/hosts.ini --become --become-user=root cluster.yml
but the installation failed:
TASK [remove-node/pre-remove : remove-node | List nodes] *********************************************************************************************************************************************************
fatal: [node1 -> node1]: FAILED! => {"changed": false, "cmd": ["/usr/local/bin/kubectl", "--kubeconfig", "/etc/kubernetes/admin.conf", "get", "nodes", "-o", "go-template={{ range .items }}{{ .metadata.name }}{{ "\n" }}{{ end }}"], "delta": "0:00:00.057781", "end": "2022-03-16 21:27:20.296592", "msg": "non-zero return code", "rc": 1, "start": "2022-03-16 21:27:20.238811", "stderr": "error: stat /etc/kubernetes/admin.conf: no such file or directory", "stderr_lines": ["error: stat /etc/kubernetes/admin.conf: no such file or directory"], "stdout": "", "stdout_lines": []}
Why the installation step tried to remove and why /etc/kubernetes/admin.conf has not been created?
Please assist.
There could be a couple of ways how can you solve your problem. First look at this github issue. Probably you can manually copy the missing file and it should work:
I solved it myself.
I copied the /etc/kubernetes/admin.conf and /etc/kubernetes/ssl/ca.* to the new node and now the scale playbook works. Maybe this is not the right way, but it worked...
The another way is to use wait for module on Ansible. You can find example of usage in this thread.
To another solution I will recommend to read this similar problem:
cluster_initialized.txt created on first fail and ansible never runs kubeadm init again. just delete that file on fail, fix the problem and run again.

Using kfp.dls.containerOp() to run multiple scripts on Kubeflow Pipelines

I have been using the Kubeflow dsl container op command to run a python script on a custom for my Kubeflow pipeline. My configuration looks something like this :
def test_container_op():
input_path = '/home/jovyan/'
return dsl.ContainerOp(
name='test container',
image="<image name>",
command=[
'python', '/home/jovyan/test.py'
],
file_outputs={
'modeule-logs' : input_path + 'output.log'
}
)
Now, I also want to run a bash script called deploy.sh within the same container. I haven't seen examples of that. Is there something like
command = [
'/bin/bash', '/home/jovyan/deploy.sh',
'python', '/home/jovyan/test.py'
]
Not sure if it's possible. Would appreciate the help.
Kubeflow job is just a Kubernetes job, thus you are limited with Kubernetes job entrypoint being a single command.
However you can still chain multiple commands into a single sh command:
sh -c "echo 'my first job' && echo 'my second job'"
So that you kubeflow command can be:
command = [
'/bin/sh', '-c', '/home/jovyan/deploy.sh && python /home/jovyan/test.py'
]

Cloud Foundry: How do I get the contents of the VCAP_SERVICES environment variable? (and only this variable!)

When I deploy an app to Cloud Foundry and attach it to instances of Cloud Foundry services,
and I use the Cloud Foundry CLI to get the environment variables: cf env my-app,
then I get an output like:
Getting env variables for app my-app in org my-org / space my-space as user#company.com...
System-Provided:
VCAP_SERVICES: {
"service1": [
// ...
],
"service2": [
// ...
]
}
VCAP_APPLICATION: {
// ...
}
User-Provided:
VARIABLE1: value
VARIABLE2: value
Running Environment Variable Groups:
CREDHUB_API: https://credhub.company.com
No staging env variables have been set
How do I filter this output to get only the contents of the environment variable VCAP_SERVICES, so that when I test/debug my app locally, it behaves as if it was attached to the instances of the Cloud Foundry services?
My goal is to write a file named default-env.json containing only:
{
VCAP_SERVICES: {
"service1": [
// ...
],
"service2": [
// ...
]
}
}
Ideally, the command to produce this output should be a zsh one-liner.
cf env my-app | sed -n '/VCAP_SERVICES/,/VCAP_APPLICATION/p' | sed '$d' | sed '1s;^;{\n;' | sed '$s/$/}/' > default-env.json
Explanation
sed -n '/VCAP_SERVICES/,/VCAP_APPLICATION/p'
keeps only the section between the regular expressions VCAP_SERVICES and VCAP_APPLICATION.
sed '$d' deletes the last line (the line containing VCAP_APPLICATION).
sed '1s;^;{\n;' prepends {\n to the first line.
sed '$s/$/}/' appends } to the end of the file.
Credits
Handy one-liners for SED
BASH Prepend A Text / Lines To a File
SED: insert text after the last line?
Another option would be:
cf curl "/v2/apps/$(cf app --guid my-super-cool-app)/env" | jq -r '.system_env_json.VCAP_SERVICES'
Explanation:
$(cf app --guid <your-app-name) will run in a subshell and get the app guid for your app. You could alternatively just replace that bit with the guid for your app, if you know it already (it'll make the command faster).
cf curl "/v2/apps/<guid>/env" will return all of the env variables for your app.
jq -r '.system_env_json.VCAP_SERVICES' picks out the bit you want.
You could optionally redirect output to a file.
Other interesting bits from that API:
.application_env_json.VCAP_APPLICATION would give you VCAP_APPLICATION.
'.environment_json' would give you any env variables you've set

Ansible Error: "[Errno 2] No such file or directory"

I'm not able to execute kubectl(v1.16.3) commands in the ansible command module.
For e.g. Creation of Namespace using ansible.
tasks:
- name: "Creating Directory"
file:
path: ~/ansible_ns/demo_namespaces
state: directory
- name: "Creating Namespaces(1/2)"
copy:
content: "apiVersion: v1 \nkind: Namespace \nmetadata: \n name: {{item}} "
dest: "~/ansible_ns/demo_namespaces/{{item}}.yml"
with_items:
- "{{ namespace }}"
- name: "Creating Namespaces(2/2)"
command: "kubectl create -f {{item}}.yml --kubeconfig=/var/lib/kubernetes/kubeconfig.yaml"
args:
chdir: ~/ansible_ns/demo_namespaces/
ignore_errors: true
with_items:
- "{{ namespace }}"
I'm ending up with the below error:
(item=ns) => {
"ansible_loop_var": "item",
"changed": false,
"cmd": "kubectl create -f ns.yml --kubeconfig=/var/lib/kubernetes/kubeconfig.yaml",
"invocation": {
"module_args": {
"_raw_params": "kubectl create -f ns.yml --kubeconfig=/var/lib/kubernetes/kubeconfig.yaml",
"_uses_shell": false,
"argv": null,
"chdir": "/root/ansible_ns/demo_namespaces/",
"creates": null,
"executable": null,
"removes": null,
"stdin": null,
"stdin_add_newline": true,
"strip_empty_ends": true,
"warn": true
}
},
"item": "ns",
"msg": "[Errno 2] No such file or directory",
"rc": 2
}
NOTE: But I'm able to do "kubectl create -f .." manually..and it is creating the stuff.
My Ansible version:
$ ansible --version
ansible 2.9.2
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/mdupaguntla/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, Aug 4 2017, 00:39:18) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]
FYI, I also tried with Ansible - 2.4.2 as well. But No luck.
My System OS: CentOS 7
My queries:
What is this error mean "[Errno 2] No such file or directory" in my context?
I came to know that Ansible introduced kubectl & k8s module: Is there anyone in the community using these.. If Yes, please let me know how to use them. If they any prerequisites - please share them
For kubectl Module: Came to know that the pre-requisite is kubectl go library.May I know where can I
get this Library.
when the kubectl version is 1.8 and ansible version is 2.4.2 - I'm able to get the K8s resources created using "kubectl create -f ..." using command module. But when I upgraded my cluster from v1.8 to v1.16.3 - I'm not able to create the resources using "kubectl create -f ..." using command module. Let me if I missed doing things.
Thanks in advance for the Community
You have to add the path for kubectl in the command module.
command: "/the/path/kubectl create -f {{item}}.yml .........."
This is because the $PATH is not updated with the path of kubectl. You can add the path to $PATH also instead of giving the path in command module.
If you use ansible 2.9.2, it has k8s module available. It provides fully declarative approach ( versus issuing imperative commands ) which is more similar to what you can find in kubernetes itself.
For example if you want to create a new namespace, just use:
- name: Create a k8s namespace
k8s:
name: testing
api_version: v1
kind: Namespace
state: present
You have to admit it looks much simpler.
Well, there are two ways to make this process better and functional.
You can try to use k8s module like this way.
- name: Create k8s catota namespace
k8s:
name: catota
api_version: v1
kind: Namespace
state: present
Or you can use the shell module as well:
- name: Create k8s catota namespace
shell: "kubectl create namespace catota"
args:
executable: /bin/bash
Troubleshooting This Issue
The Error:
(item=ns) => {
"ansible_loop_var": "item",
"changed": false,
"cmd": "kubectl create -f ns.yml --kubeconfig=/var/lib/kubernetes/kubeconfig.yaml",
"invocation": {
"module_args": {
"_raw_params": "kubectl create -f ns.yml --kubeconfig=/var/lib/kubernetes/kubeconfig.yaml",
"_uses_shell": false,
"argv": null,
"chdir": "/root/ansible_ns/demo_namespaces/",
"creates": null,
"executable": null,
"removes": null,
"stdin": null,
"stdin_add_newline": true,
"strip_empty_ends": true,
"warn": true
}
},
"item": "ns",
"msg": "[Errno 2] No such file or directory",
"rc": 2
}
First, notice that this states "_uses_shell": false,. This is because it is using Command instead of shell. This is also disguising the error code. If we switch to shell and re-run we get:
"msg": "non-zero return code",
"rc": 127,
"start": "2021-09-03 13:48:12.184639",
"stderr": "/bin/bash: <PROGRAM>: command not found",
(details on exit codes https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html )
The /bin/bash is the giveaway. Doing which kubectl you might get something like /usr/local/bin/kubectl.
You either need to update the ansible command to use /usr/local/bin/kubectl or update the $PATH for /bin/bash/ to find it.

mongo --shell file.js and "use" statement

can't find solution for simple question:
I have file text.js
use somedb
db.somecollection.findOne()
When I run this file in cmd with redirection command from file:
"mongo < text.js"
it's work properly
But when I try this way
"mongo text.js" or "mongo --shell test.js"
I got this error message
MongoDB shell version: 2.2.0
connecting to: test
type "help" for help
Wed Dec 05 16:05:21 SyntaxError: missing ; before statement pathToFile\test.js.js:1
failed to load: pathToFile\test.js.js
It's fail on "use somedb". If I remove this line, it's run without error, but console is clear.
is there any idea, what is this and how to fix?
I'm tying to find sollution for this, to create build tool for Sublime Text 2.
default build file was
{
"cmd": ["mongo","$file"]
}
but in this case I get the error above
PS. right after posting this question I find sollution for SublimeText2:
{
"selector": "source.js",
"shell":true,
"cmd": ["mongo < ${file}"]
}
PSS. right after posting this question I find sollution for SublimeText3:
{
"selector": "source.js",
"shell":true,
"cmd": ["mongo","<", "$file"]
}
this build tool work properly
use dbname is a helper function in the interactive shell which does not work when you are using mongo shell with a JS script file like you are.
There are multiple solutions to this. The best one, IMO is to explicitly pass the DB name along with host and port name to mongo like this:
mongo hostname:27017/dbname mongoscript.js // replace 27017 with your port number
A better way to do this would be to define the DB at the beginning of your script:
mydb=db.getSiblingDB("yourdbname");
mydb.collection.findOne();
etc.
The latter is preferable as it allows you to interact with multiple DBs in the same script if you need to do so.
You can specify the database while starting the mongo client:
mongo somedb text.js
To get the output from the client to stdout just use the printjson function in your script:
printjson(db.somecollection.findOne());
Mongo needs to be invoked from a shell to get that mode, with Ansible you would have this:
- name: mongo using different databases
action: shell /usr/bin/mongo < text.js
Instead of this:
- name: mongo breaking
command: /usr/bin/mongo < text.js
This is what finally worked for me on Windows + Sublime Text 2 + MongoDB 2.6.5
{
"selector": "source.js",
"shell":true,
"cmd": ["mongo","<", "$file"],
"working_dir" : "C:\\MongoDB\\bin"
}