If the osh configuration file is going to be used for database access, then it may contain a plaintext database password. It is therefore good practice to restrict access this file to, e.g. set permissions to 600.
from osh.config import *Database and cluster configuration is done using field and slice notation. For example, to specify that the sql command connects to the family database as 'jao':
osh.sql.family.database = 'family' osh.sql.family.user = 'jao'
Slice notation is also supported, e.g.
osh.sql['family'].user = 'jao'This is useful in case a database or cluster name is known dynamically, or is not a legal Python identifier.
osh sql family 'select count(*) from request' $family is the name of a database profile, specified in .oshrc. The profile specifies a module implementing the connect method of a DBAPI 2.0 driver, and the arguments to the module's connect method, e.g.
osh.sql.family.driver = 'pg8000.dbapi' osh.sql.family.host = 'localhost' osh.sql.family.database = 'familydb' osh.sql.family.user = 'jao' osh.sql.family.password = 'l3tme1n'This specification results in a connection being created as pg8000.dbapi.connect(host = 'localhost', database = 'familydb', user = 'jao', password = 'l3tme1n').
The DBAPI driver is not included with osh. It needs to be in your python environment, located on PYTHONPATH, in site-packages, or in a location specified by sitecustomize.py.
osh also provides access to postgres databases using the pygresql driver as follows:
osh.sql.family.dbtype = 'postgres' osh.sql.family.host = 'localhost' osh.sql.family.db = 'familydb' osh.sql.family.user = 'jao' osh.sql.family.password = 'l3tme1n'A default database profile can be specified by assigning a value to osh.sql, e.g.
osh.sql = 'family'If this is done, then the sql command can omit the database profile name, e.g.
osh sql 'select count(*) from request' $
osh @fred [ sql family 'select name, age from person' ] $Each node of fred's cluster must configure a database profile named family in its .oshrc file.
On the local node (the one on which the above command is entered), the cluster fred must be configured, e.g.
osh.remote.fred.hosts = ['192.168.100.101', '192.168.100.102', '192.168.100.103']Access to the cluster is done as root. If you want to connect as some other user, specify the user as follows:
osh.remote.fred.user = 'zack'Remote access is done using ssh, and osh cannot handle any prompts, e.g. for password or a passphrase. If you can connect to a host silently using ssh, e.g. by setting up an ssh agent, then that will work for osh. If you use the ssh -i option, then the identity can be specified in .oshrc, e.g.
osh.remote.fred.identity = '~/.ssh/fred.pem'(You can check your ssh connection using the testssh command, e.g. osh @fred [ testssh ] $.)
When a remote command is run on a cluster, each row of output identifies the node that generated the output, e.g.
zack$ osh @fred [ sql family 'select name, age from person' ] $ ('192.168.100.101', 'hannah', 15) ('192.168.100.101', 'julia', 10) ('192.168.100.102', 'alexander', 16) ('192.168.100.102', 'nathan', 15) ('192.168.100.102', 'zoe', 11) ('192.168.100.103', 'danica', 1)The hosts part of a cluster specification can also be done using a dict, in which the key is a name for the node, and the value is the IP address, e.g.
osh.remote.fred.hosts = {'101': '192.168.100.101', '102': '192.168.100.102', '103': '192.168.100.103'}The node names are used in command output in place of IP addresses, e.g.
zack$ osh @fred [ sql familydb 'select name, age from person' ] $ ('101', 'hannah', 15) ('101', 'julia', 10) ('102', 'alexander', 16) ('102', 'nathan', 15) ('102', 'zoe', 11) ('103', 'danica', 1)These examples assume that each node of cluster fred has a .oshrc file that configures a database profile named family. It is also possible to configure database access even when each node specifies a different database profile, e.g.
osh.remote.fred.hosts = {'101': {'host': '192.168.100.101', 'db_profile': 'db1'}, '102': {'host': '192.168.100.102', 'db_profile': 'db2'}, '103': {'host': '192.168.100.103', 'db_profile': 'db3'}}With this configuration osh @fred [ sql 'select ...' ] ... accesses db1 on node 101, db2 on node 102, and db3 on node 103.
The complete rules for selecting a database profile are as follows:
zack$ osh gen 10 ^ f 'x: (x**2, x**3)' $The same computation can be done by writing a function to compute squares and cubes:
def square_and_cube(x): return x**2, x**3and putting this function definition in .oshrc. Then, the osh command above can be rewritten as:
zack$ osh gen 10 ^ f 'x: square_and_cube(x)' $
osh.path = ['/usr/local/foobar']or the osh interpreter will not find xyz when used in an osh command sequence.
The value of osh.path is a list so that custom commands can be placed in any number of directories.