Introduction

JS7 can be used to execute any scripts, executables and programs including Python® scripts.

  • Python® is a frequently used scripting language available for Linux, MacOS, Windows and other platforms.
  • Docker® offers a Python® SDK to manage containers, see https://docs.docker.com/engine/api/sdk/
  • This article explains how to use the Python® SDK for Docker® with JS7 job scripts.

Building Blocks

The following building blocks make up the solution:

  • Install the Python® SDK as available from https://github.com/docker/docker-py

    Install docker-py plugin
    pip install docker


    • Explanation:
      • Python® has to be available on the machine that the JS7 Agent is operated for. This includes Agents operated on premises and with containers.
      • This is just an example, there are more ways of installing the Python® SDK for Docker®.

  • Create a workflow with a shell job that imports the Python® SDK like this:

    Import docker-py plugin with Agents operated for Unix
    #!/usr/bin/python
    
    import docker
    
    client = docker.from_env()
    ...
    Import docker-py plugin with Agents operated for Windows
    @@findstr/v "^@@f.*&" "%~f0"|python.exe -&goto:eof
    
    import docker
    
    client = docker.from_env()
    ...


    Explanation
    :

  • Create JS7 - Job Resources for your containers.
    • Best practice is to use a Job Resource per container.
    • This allows specification of any properties of a container such as image name, host name, container name, mounts etc. from variables of a Job Resource.

Examples

The examples make use of a Job Resource and a number of Workflows that are managed with the Configuration view like this:

Job Resource for a Container

Download (upload .json): agent-2-0-standalone.jobresource.json

When managing a Job Resource this view offers two sub-views:

  • The Arguments sub-view allows specifying variables which hold pairs of variable names and values.
    • Arguments can be used for parameterization of JVM jobs and they can be used in workflow instructions such as the JS7 - If Instruction.
  • The Environment Variables sub-view allows specifying environment variables from pairs of names and values that are forwarded to shell jobs.
    • Environment Variables can be used for parameterization of shell jobs.
  • The following names and values are examples of frequently used parameters when setting up containers, for example with the docker run command:
    • repository_name: Identifier of the repository
    • image_name: Identifier of the image that is used to instantiate the container.
    • container_name: Name assigned the container.
    • host_name:  Hostname (FQDN) assigned the container.
    • etc.


Consider the following example of the Environment Variables sub-view:

  • Names of environment variables can be freely chosen within the limits of the operating system. Names are stored with uppercase letters.
  • The values of environment variables reference variables previously configured with the Arguments sub-view.
    • This allows the use of variables from both JVM jobs and shell jobs.
    • As an alternative it is possible to directly assign strings to the values of environment variables and not to use the Arguments sub-view.

Workflow to start a Container

The example uses a single job that runs on an Agent with access to the Docker® daemon.


The job script of the single job in this workflow looks like this:

Example of job script to start a container
#!/usr/bin/python

import docker
from docker.types import Mount
import os

client = docker.from_env()

container = client.containers.run( image=os.environ.get('REPOSITORY_NAME') + ':' + os.environ.get('IMAGE_NAME'), \
                                   hostname=os.environ.get('HOST_NAME'), \
                                   network=os.environ.get('NETWORK_NAME'), \
                                   detach=True, \
                                   environment={ \
                                                 'RUN_JS_HTTP_PORT': 4445, \
                                                 'RUN_JS_HTTPS_PORT': 4443, \
                                                 'RUN_JS_JAVA_OPTIONS': os.environ.get('AGENT_JAVA_OPTIONS'), \
                                                 'RUN_JS_JOB_JAVA_OPTIONS': os.environ.get('JOB_JAVA_OPTIONS'), \
                                                 'RUN_JS_USER_ID': os.environ.get('USER_ID') \
                                               }, \
                                   mounts=[Mount(target="/var/sos-berlin.com/js7/agent/var_4445", source=os.environ.get('IMAGE_NAME') + "-var", type="volume")], \
                                   name=os.environ.get('CONTAINER_NAME'), \
                                   ports={ '4445/tcp': os.environ.get('HTTP_PORT'), '4443/tcp': os.environ.get('HTTPS_PORT') }, \
                                   remove=True, \
                                   tty=True \
                                 )
print("Container started: ", container.id)

print("Container logs:")
print(container.logs())


Explanation:

  • The job script uses a number of parameters as it maps all options used to run a JS7 Agent from a container as explained in the JS7 - Agent Installation for Containers article.
  • The relevant part is the client.containers.run() function which is parameterized with frequently used options for specifying the image name, hostname, network name etc.
  • Environment variables are available from the assigned Job Resource.
  • The optional part includes displaying log output created on start-up of the container using the container.logs() function.

Workflow to stop a Container

The example uses a single job which runs on an Agent with access to the Docker® daemon.


The job script of the job in this workflow looks like this:

Example of job script to stop a container
#!/usr/bin/python

import docker
import os

client = docker.from_env()

container = client.containers.get( os.environ.get('CONTAINER_NAME') )
container.stop()
print("container stopped: ", container.id)


Explanation:

  • The job script reads the environment variable CONTAINER_NAME to identify the container to be stopped.
  • This environment variable is provided by the agent-2-0-standalone Job Resource.

Workflow to execute commands in a Container

The example makes use of a single job that runs on an Agent with access to the Docker® daemon.

  • Download (upload .json): pdExecContainer.workflow.json
  • The job is assigned the agent-2-0-standalone Job Resource that holds the parameters which identify the container to be stopped.
  • Consider the command workflow variable which holds the command to be executed in the container. Adding a variable from a workflow increases flexibility by allowing such variables to be updated for use with different values from each order that executes the workflow.


The job script of the single job in this workflow looks like this:

Example of job script to execute commands in a container
#!/usr/bin/python

import docker
import os

client = docker.from_env()

container = client.containers.get( os.environ.get('CONTAINER_NAME') )
rc = container.exec_run( \
							cmd=os.environ.get('COMMAND'), \
                           	environment={ \
                          		'JS7_AGENT_HOME': os.environ.get('JS7_AGENT_HOME'), \
                        		'JS7_AGENT_DATA': os.environ.get('JS7_AGENT_DATA') \
                    		}, \
                    		tty=True, \
                    		user="jobscheduler" \
                        )

print("container exec return code: ", rc)


Explanation:

  • The job script reads the environment variable CONTAINER_NAME to identify the container to be stopped.
  • This environment variable is provided by the agent-2-0-secondary Job Resource.