2

I am writing a bash script on CentOS 7.5 that will execute some MongoDB commands. One of these commands will set replication servers. According to project, number of servers can be different.

I have this associative array that is the hostname an IPs of servers (I used an associative array because other parts of code needed it). In this example I have three servers:

  declare -A rep_hostname
  rep_hostname=( [test1]='172.1.1.1' [test2]='172.1.1.2' [test3]='172.1.1.3'  )

When having three servers, I have to run this command:

  rs.initiate( { _id : "opino-rs", members: [ { _id: 0, host: "172.1.1.1:2701" }, 
  { _id: 1, host: "172.1.1.2:2701" }, { _id: 2, host: "172.1.1.3:2701" } ]})

If my array has two server, I have this:

  rs.initiate( { _id : "opino-rs", members: [ { _id: 0, host: "172.1.1.1:2701" }, 
  { _id: 1, host: "172.1.1.2:2701" } ]})  

I need to generate this command then execute it. The problem is I can't generate it. I tried few codes they weren't even close to what I wanted.
How can I do this?

3
  • Your expected JSON documents are both broken. They lack a closing ] and the keys are not quoted. Consider updating the question.
    – Kusalananda
    Dec 21, 2020 at 12:33
  • How do you do the conversion from your associative array's keys to the _id values?
    – Kusalananda
    Dec 21, 2020 at 12:50
  • @Kusalananda there is no conversion between them. but it must start from 0. if i have 5 servers ir will be 0,1,2,3,4. i updated my json. Dec 21, 2020 at 13:13

1 Answer 1

2
#!/bin/bash

declare -A rep_hostname
rep_hostname=( [test1]='172.1.1.1' [test2]='172.1.1.2' [test3]='172.1.1.3' )

json=$(
        jo _id=opino-rs members="$(
                jo -a "${rep_hostname[@]/%/:2701}" |
                jq -c 'to_entries | map({ "_id": .key, "host": .value })'
        )"
)

printf 'rs.initiate(%s)\n' "$json"

Testing:

$ bash script.sh
rs.initiate({"_id":"opino-rs","members":[{"_id":0,"host":"172.1.1.3:2701"},{"_id":1,"host":"172.1.1.2:2701"},{"_id":2,"host":"172.1.1.1:2701"}]})

This uses both jo and jq. The jo utility is a tool for creating JSON in the shell. jo will make sure that the generated JSON is properly quoted and encoded. The jq utility is a tool for parsing and processing JSON in the shell.

I'm using jo to create a JSON list of host names from the list of IP addresses in your associative array. Before creating the JSON array, I add :2701 to the end of each IP address by means of a parameter substitution.

$ jo -a "${rep_hostname[@]/%/:2701}"
["172.1.1.3:2701","172.1.1.2:2701","172.1.1.1:2701"]

This is read by jq which modifies it into the list of JSON objects that we want to assign to the members key in the final JSON:

$ jo -a "${rep_hostname[@]/%/:2701}" | jq -c 'to_entries | map({ "_id": .key, "host": .value })'
[{"_id":0,"host":"172.1.1.3:2701"},{"_id":1,"host":"172.1.1.2:2701"},{"_id":2,"host":"172.1.1.1:2701"}]

This is use as input to jo again to construct the final JSON document.

At the end of the script, the generated JSON document is simply inserted into the parentheses in the string rs.initiate() using a call to printf.

Since I don't use MongoDB, I can't say how to then execute the result of this in the best way.

See also:

2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.