Birst_Command
Birst Command is a Ruby gem that allows you to build Ruby scripts that interface with the Birst Web API. It also comes with a simple command line tool that can be used to execute simple API requests from the command line.
Note: this is not an officially-sanctioned Birst project. I'm just a Birst user that needed to set up a very basic Ruby interface.
Installation & Setup
SPECIAL NOTE: Many changes since version 0.5.0. Read the Changelog.
Prerequisites: Ruby > 2.0 and rubygems.
Install the gem using gem install Birst_Command
or using rvm or
rbenv/bundler as you prefer.
After installing, you'll need to create a Birst Command config file that contains the credentials you'll use to connect to Birst. This is a yaml file that should look something like
---
session:
wsdl: "https://app2101.bws.birst.com/CommandWebService.asmx?WSDL"
endpoint: "https://app2101.bws.birst.com/CommandWebService.asmx"
username: "BirstUsername"
password: "EncryptedPassword"
soap_log: true
soap_log_level: :debug
Save it to $HOME/.birstcl
. Most users should only need to modify
the username and password. (Note: do not use login.bws.birst.com
since it does not use an updated WSDL; a specific app server must be
specified). Since I have a strong aversion to storing passwords in
plaintext, the password in the config file needs to use and encrypted
password. Birst Command comes bundled with a password encryptor
called Envcrypt that can be
executed via
$ envcrypt -s mypassword
which should give an output similar to
Encrypted Secret: 2KwUMeJIqsjPWWF9Fw0I+w==
ENVCRYPT_KEY='V/V919RKnz8l2M002336bg==$ARoQfp/9pfv5kVN/ysRuStLuTWJFZhQF1f49xkHbcwQ=$YAjVhHOXlcagmZoFYgPWdQ=='
WARNING: It is critical that the key and encryption password be stored separately!
Copy and paste the encrypted password (aka "secret') into the
$HOME/.birstcl
config file. You will also need to ensure that the
ENVCRYPT_KEY
environment variable is set as indicated above. If you're
running in a development environment, you can include these in your
bash ~/.profile
file.
Also note that the YAML config file is pre-processed with ERB. So if
you also want to keep your encrypted password in an environment
variable, you could replace the password
line above with
...
password: "<%= ENV['MY_ENCRYPTED_PASSWORD'] %>"
...
Usage - Birst command line tool
Birst Command also installs a rudimentary command line tool for interacting with the Birst web API. It's still very simple. If you want more functionality, please drop me a line in the github repository.
To use the command line tool, put the config file created above in
$HOME/.birstcl. Then run Birst commands using birstcl
. You'll have to refer
to the Birst Documentation
for a full list of commands. All birst commands should be submitted using snake_case
and arguments using the exact camelCase specified in the Birst documentation. See
below for an explanation of this bizarre requirement. Here are some examples:
List spaces
birstcl -c list_spaces
Get list of sources for a space
birstcl -c get_sources_list -a '{ spaceID: "383nf0d7-3875-3829-3hff-faba8936180a" }'
Copy space with options
birstcl -c copy_space -a '{ spFromID: "9ab9865c-37a8-0586-e856-ddd3856a0371", spToID: "3957a9b7-38c1-175v-3985-1957f1836a93", mode: "replicate", options: "data;repository;settings-basic" }'
Cookies
Many Birst web API commands return a job token that can be used to check up on the status of a job as it progresses. The job tokens are tied to a specific server, and the only way to direct your login to a specific server is to use cookies. So, if you wanted to copy a space with one command and then check whether the job is complete with another, you need to do something like the following.
Copy a space and write a cookie file
birstcl -c copy_space -a '{ spFromID: "f9cb64fe-58a1-1db6-a7a8-9f091b4ea96f", spToID: "12913e53-3eac-4f98-91ab-2fqf345e22e5", mode: "replicate", options: "data;datastore;repository;useunloadfeature" }' -w ./cookie
Note the job token returned as result and then run another command to check whether the job is complete by reading the cookie file
birstcl -c is_job_complete -a '{ jobToken: "9f636262f4c73d7503bf240ea08de040" }' -r ./cookie
Usage - As Ruby library
In your Ruby program, include the Birst Command gem and load the config file via
require 'rubygems'
require 'bundler/setup'
require 'birst_command'
Birst_Command.load_settings_from_file(file)
# Or you can forego the settings file and set them explicitly in code via
Birst_Command::Settings.session.username = "George"
Birst commands are submitted in session blocks, which automatically perform the process of logging in, tracking the login token, and logging out. For example, to list all spaces that you have rights to, you can submit the following code
Birst_Command::Session.new do |bc|
spaces = bc.list_spaces
puts "#{JSON.pretty_generate spaces}"
end
Which would return something like
{
"user_space": [
{
"name": "MyGreatSpace",
"owner": "name@myplace.com",
"id": "b413207d-3fe2-4309-1b4a-ac8e961daad2"
},
{
"name": "MyOtherGreatSpace",
"owner": "name@myplace.com",
"id": "a113207d-3fe2-4310-1b4a-b58e961da123"
}
]
}
The spaces
variable is a Ruby hash parsed from the SOAP response.
The structure of the returned hash follows the structure that Birst
returns.
Command arguments
Some Birst API commands require arguments. All arguments are supplied as an argument hash. All arguments are mandatory even if they're blank/null (Birst web API requirement). For example, to create a new space,
Birst_Command::Session.new do |bc|
new_space_id = bc.create_new_space :spaceName => "myNewSpace", :comments => "Just testing",:automatic => "false"
end
Cookies
The start session block can also accept an argument named use_cookie
to
pass a cookie to be used during startup. For example, suppose we start
a copy job and save the session_cookie
and job_token
in variables.
session_cookie = nil
job_token = nil
Bist_Command::Session.new do |bc|
job_token = bc.copy_space :spFromID => @from_id, :spToID => @to_id, :mode => "replicate", :options => "data;datastore;useunloadfeature"
session_cookie = bc.auth_cookie
end
In a subsequent session we can use the session_cookie
on login via
is_job_complete = false
Birst_Command::Session.new auth_cookie: session_cookie do |bc|
is_job_complete = bc.is_job_complete :jobToken => job_token
end
puts "COMPLETE? #{is_job_complete}"
Helper methods
I find some of the Birst API responses to be rather cumbersome. For
example, why do I need hash with a single user_space
key when I
run the list_spaces
command? I'd
rather have an array of hashes here. To that end I find it convenient
to define helper methods that extend the Session class to simplify
some of this. To override the return value of the native
list_spaces
command, you can do the following
class Birst_Command::Session
def list_spaces(*args)
result = command __method__, *args
[result[:user_space]].flatten
end
end
You can then execute the same list_spaces
command above, but you get
an array of hashes rather than hash with a key that points to an array
of hashes.
I have not included any of these helper methods in the Birst Command gem because what I find helpful, you may not. Birst Command just provides the basic interface.
camelCase/snake_case issues
Birst Command uses Savon as
the underlying framework used to communicate with the Birst SOAP API.
Savon expects commands in snake_case format and converts them into
camelCase when submitted to the Birst API (e.g., list_spaces
is
converted to listSpaces
). This behavior is not configurable.
Savon also has options for converting the arguments of parameters from
snake_case into camelCase. Unfortunately, the Birst Web API is not
entirely consistent in its use of camelCase for arguments (e.g.,
spaceId
is used in deleteSpace
but spaceID
is used in
listUsersInSpace
). This inconsistency requires us to submit
commands as snake_case and arguments as the camelCase that Birst
uses.