0

I am trying to run a series of commands to create and add the same type of user to multiple mongodbs. Currently I make a connection to the pod I want: connect = os.system("kubectl exec -n epic-dev zerodtmongo-0 -it -- /bin/sh"

but my python script ends there and the new shell for that pod opens within the python terminal.

I would like to continue the python script to execute this block of code within multiple pods I have stored in a list.

    # Create roles to create roles 'listDatabase' & 'readChangeStream'
mongo -u admin -p admin localhost:27017/admin <<-EOF
  db.runCommand(
  {
    createRole: "listDatabases", 
    privileges: [
      { 
        resource: {cluster : true}, 
        actions: ["listDatabases"]
      }
    ],
    roles: []
  }
);

  db.runCommand(
  {
    createRole: "readChangeStream",
    privileges: [
      { 
        resource: { db: "", collection: ""}, 
        actions: [ "find", "changeStream" ] 
      }
    ],
    roles: []
   });
EOF


# Create a debezium user
mongo -u admin -p admin localhost:27017/admin <<-EOF
  db.createUser(
  {
    user: 'foo',
    pwd: 'bar',
    roles: [
      { role: "read", db: "admin" }
    ]
  });
EOF

Something like:

for pods in list:
    connect(pod)
    add user
    close connection

2 Answers 2

4

you should use the python Kubernetes client to leverage the maximum benefit.

kubernetes-client-python

Here is the working example that expects the Kube config already set up.

helm install my-release bitnami/mongodb

from click import command
from kubernetes import client, config
from kubernetes.stream import stream

def pod_exec(name, namespace, command, api_instance):
    exec_command = ["/bin/sh", "-c", command]

    resp = stream(api_instance.connect_get_namespaced_pod_exec,
                  name,
                  namespace,
                  command=exec_command,
                  stderr=True, stdin=False,
                  stdout=True, tty=False,
                  _preload_content=False)

    while resp.is_open():
        resp.update(timeout=1)
        if resp.peek_stdout():
            print(f"STDOUT: \n{resp.read_stdout()}")
        if resp.peek_stderr():
            print(f"STDERR: \n{resp.read_stderr()}")

    resp.close()

    if resp.returncode != 0:
        raise Exception("Script failed")

command = """mongo -u root -p $MONGODB_ROOT_PASSWORD localhost:27017/admin <<-EOF
  db.runCommand(
  {
    createRole: "listDatabases", 
    privileges: [
      { 
        resource: {cluster : true}, 
        actions: ["listDatabases"]
      }
    ],
    roles: []
  }
);

  db.runCommand(
  {
    createRole: "readChangeStream",
    privileges: [
      { 
        resource: { db: "", collection: ""}, 
        actions: [ "find", "changeStream" ] 
      }
    ],
    roles: []
   });
EOF"""
print (command)
pod = "my-release-mongodb-7bcd6b847-qzjxz"
config.load_kube_config()

v1 = client.CoreV1Api()

pod_exec(pod, "mongodb", command, v1)

python3 k8_create_db.py

enter image description here

Sign up to request clarification or add additional context in comments.

7 Comments

what is helm install my-release bitnami/mongodb used for?
For mongodb, you don't need this as your already have one
Specify the pod name and name space in the execs command
I am running into a 403 error kubernetes.client.exceptions.ApiException: (0) Reason: Handshake status 403 Forbidden. This has to do with connect_get_namespaced_pod_exec no?
As i mentioned it expect you already configure the kubeconfig file
|
2

Using official K8s client,

Ref : https://github.com/kubernetes-client/python/blob/master/examples/pod_exec.py

import time

from kubernetes import config
from kubernetes.client import Configuration
from kubernetes.client.api import core_v1_api
from kubernetes.client.rest import ApiException
from kubernetes.stream import stream


def exec_commands(api_instance):
    name = 'busybox-test'
    resp = None
    try:
        resp = api_instance.read_namespaced_pod(name=name,
                                                namespace='default')
    except ApiException as e:
        if e.status != 404:
            print("Unknown error: %s" % e)
            exit(1)

    exec_command = ['/bin/sh']
    resp = stream(api_instance.connect_get_namespaced_pod_exec,
                  name,
                  'default',
                  command=exec_command,
                  stderr=True, stdin=True,
                  stdout=True, tty=False,
                  _preload_content=False)
    commands = [
        "echo This message goes to stdout",
        "echo \"This message goes to stderr\" >&2",
    ]

    while resp.is_open():
        resp.update(timeout=1)
        if resp.peek_stdout():
            print("STDOUT: %s" % resp.read_stdout())
        if resp.peek_stderr():
            print("STDERR: %s" % resp.read_stderr())
        if commands:
            c = commands.pop(0)
            print("Running command... %s\n" % c)
            resp.write_stdin(c + "\n")
        else:
            break

    resp.write_stdin("date\n")
    sdate = resp.readline_stdout(timeout=3)
    print("Server date command returns: %s" % sdate)
    resp.write_stdin("whoami\n")
    user = resp.readline_stdout(timeout=3)
    print("Server user is: %s" % user)
    resp.close()


def main():
    config.load_kube_config()
    try:
        c = Configuration().get_default_copy()
    except AttributeError:
        c = Configuration()
        c.assert_hostname = False
    Configuration.set_default(c)
    core_v1 = core_v1_api.CoreV1Api()

    exec_commands(core_v1)


if __name__ == '__main__':
    main()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.