Skip to content
This repository has been archived by the owner on Jan 14, 2020. It is now read-only.

[#8] - POST Zeppelin Notebooks #15

Merged
merged 4 commits into from
Jun 23, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions conf/service-installer.conf
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ service-names=["ZEPPELIN", "NIFI"]

[ZEPPELIN]
install-commands=[ "hdp-select status hadoop-client | sed 's/hadoop-client - \\([0-9]\\.[0-9]\\).*/\\1/'", "cp -r ../ambari-services/ambari-zeppelin-service /var/lib/ambari-server/resources/stacks/HDP/$VERSION/services/ZEPPELIN", "ambari-server restart"]
protocol=http
server=localhost
port=9995

Expand Down
20 changes: 17 additions & 3 deletions scripts/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
# All params are read as strings

def read_config(configFile):
cwd = os.getcwd()
path = cwd + '/' + configFile
path = get_conf_dir() + configFile

if not os.path.isfile(path):
raise IOError('could not find file at '+path )
Expand All @@ -27,4 +26,19 @@ def read_config(configFile):
for key in config.options(section):
params[section][key] = config.get(section, key)

return params
return params

def get_conf_dir():
dirs = [str(os.getcwd()), str(os.curdir), '../']

for loc in dirs:
if not (str(loc).endswith('/')):
loc += '/'
loc += 'conf/'
if(os.path.exists(loc)):
return loc

raise EnvironmentError('Could not find conf directory')



43 changes: 33 additions & 10 deletions scripts/service_installer.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Script which installs Zeppelin as an Ambari Service
import config, sys, platform, json, time
import config, sys, platform, json, time, os
from shell import Shell
from curl_client import CurlClient

Expand All @@ -22,7 +22,7 @@ def install_hdp_select():
else:
fullname = fullname + dist_info[1][0] + dist_info[1][1]

conf = config.read_config('../conf/service-installer.conf')
conf = config.read_config('service-installer.conf')
urls = conf['HDP-SELECT']
url = ''
if fullname == 'centos6':
Expand Down Expand Up @@ -52,7 +52,7 @@ def install_hdp_select():
return False
else:
return True

def is_hdp_select_installed():
sh = Shell()
output = sh.run('which hdp-select')
Expand All @@ -70,12 +70,35 @@ def is_ambari_installed():
else:
return True

# Uses the conf/zeppelin/notes directory to upload pre-made notebooks
def add_zeppelin_notebooks():
all_success = True
note_dir = config.get_conf_dir() + 'zeppelin/notes'
for item in os.listdir(note_dir):
item_path = note_dir + '/' + item
if os.path.isfile(item_path) and str(item).endswith('.json'):
result = post_notebook(item_path)
if not result:
all_success = False
return all_success

# log ("POSTED NOTEBOOK: " + str(post_notebook(item_path)))


def post_notebook(notebook_path):
conf = config.read_config('service-installer.conf')['ZEPPELIN']
client = CurlClient(proto=conf['protocol'], server=conf['server'], port=int(conf['port']))
path = '/api/notebook'

output = client.make_request('POST', path, options='-i -H "Content-Type: application/json" -d @' + notebook_path )
if '201 created' in output[0].lower():
# log successful note created
return True
else:
# log failed note creation (and to import manually)
return False

def install_zeppelin(conf_dir):

if not conf_dir.endswith('/'):
conf_dir += '/'

def install_zeppelin():
if not is_ambari_installed():
raise EnvironmentError('You must install the demo on the same node as the Ambari server. Install Ambari here or move to another node with Ambari installed before continuing')

Expand All @@ -85,7 +108,7 @@ def install_zeppelin(conf_dir):
if not installed:
raise EnvironmentError('hdp-select could not be installed. Please install it manually and then re-run the setup.')

conf = config.read_config(conf_dir + 'service-installer.conf')
conf = config.read_config('service-installer.conf')
cmds = conf['ZEPPELIN']['install-commands']
cmds = json.loads(conf['ZEPPELIN']['install-commands'])

Expand All @@ -108,7 +131,7 @@ def install_zeppelin(conf_dir):
# We've copied the necessary files. Once that completes we need to add it to Ambari

print('Checking to make sure service is installed')
ambari = config.read_config(conf_dir + 'global-config.conf')['AMBARI']
ambari = config.read_config('global-config.conf')['AMBARI']
installed = check_ambari_service_installed('ZEPPELIN', ambari)
cont = ''
if not installed:
Expand Down
74 changes: 49 additions & 25 deletions tests/test_config.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,53 @@
import mock, unittest
from env import scripts
from scripts import config
from ConfigParser import MissingSectionHeaderError

def test_good_file():
params = config.read_config('res/good-test.properties')
assert params['SECTION1']['key1'] == 'val1'
assert params['SECTION2']['key2'] == 'val2'
assert params['SECTION3']['key3'] == 'val3'
assert params['SECTION3']['key4'] == 'val4'
assert len(params['SECTION3']) > 1
assert len(params['SECTION2']) > 0
assert len(params['SECTION1']) > 0
assert len(params) == 3

def test_missing_header():
try:
params = config.read_config('res/bad-test.properties')
assert 0
except MissingSectionHeaderError as err:
assert 1

def test_missing_file():
try:
params = config.read_config('nofile')
assert 0
except IOError as e:
if 'could not find file' not in e.message:
assert 0
class TestConfig(unittest.TestCase):

@mock.patch('scripts.config.get_conf_dir', return_value='')
def test_good_file(self, mock1):
params = config.read_config('res/good-test.properties')
assert params['SECTION1']['key1'] == 'val1'
assert params['SECTION2']['key2'] == 'val2'
assert params['SECTION3']['key3'] == 'val3'
assert params['SECTION3']['key4'] == 'val4'
assert len(params['SECTION3']) > 1
assert len(params['SECTION2']) > 0
assert len(params['SECTION1']) > 0
assert len(params) == 3

@mock.patch('scripts.config.get_conf_dir', return_value='')
def test_missing_header(self, mock1):
try:
params = config.read_config('res/bad-test.properties')
assert 0
except MissingSectionHeaderError as err:
assert 1

@mock.patch('scripts.config.get_conf_dir', return_value='')
def test_missing_file(self, mock1):
try:
params = config.read_config('nofile')
assert 0
except IOError as e:
if 'could not find file' not in e.message:
assert 0

@mock.patch('os.path.exists', return_value=False)
def test_bad_env(self, mock1):
try:
config.get_conf_dir()
assert 0
except EnvironmentError as e:
assert str(e) == 'Could not find conf directory'


@mock.patch('os.path.exists', return_value=True)
@mock.patch('os.getcwd', return_value='adir')
def test_good_env(self, mock1, mock2):
try:
cdir = config.get_conf_dir()
assert 'conf/' in cdir
except EnvironmentError as e:
assert str(e) == 'Could not find conf directory'
91 changes: 48 additions & 43 deletions tests/test_service_installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class TestZeppelinInstall(unittest.TestCase):
@mock.patch('scripts.service_installer.is_ambari_installed', return_value=False)
def test_zeppelin_ambari_bad(self, mock):
try:
service_installer.install_zeppelin('../conf/service-installer.conf')
service_installer.install_zeppelin()
self.fail('Cannot continue installation without Ambari')
except EnvironmentError as e:
assert str(e.message) == 'You must install the demo on the same node as the Ambari server. Install Ambari here or move to another node with Ambari installed before continuing'
Expand All @@ -116,7 +116,7 @@ def test_zeppelin_ambari_bad(self, mock):
@mock.patch('scripts.service_installer.install_hdp_select', return_value=False)
def test_zeppelin_ambari_good(self, mock, mock2, mock3): #Also HDP select bad
try:
service_installer.install_zeppelin('../conf/service-installer.conf')
service_installer.install_zeppelin()
self.fail('Cannot continue installation without hdp-select')
except EnvironmentError as e:
assert str(e.message) == 'hdp-select could not be installed. Please install it manually and then re-run the setup.'
Expand All @@ -127,7 +127,7 @@ def test_zeppelin_ambari_good(self, mock, mock2, mock3): #Also HDP select bad
@mock.patch('scripts.service_installer.check_ambari_service_installed', return_value=True)
@mock.patch('__builtin__.raw_input', return_value='y')
def test_zeppelin_check_is_good(self, mock, mock2, mock3, mock4, mock5):
assert service_installer.install_zeppelin('../conf') == True
assert service_installer.install_zeppelin() == True


@mock.patch('scripts.service_installer.is_ambari_installed', return_value=True)
Expand All @@ -136,7 +136,7 @@ def test_zeppelin_check_is_good(self, mock, mock2, mock3, mock4, mock5):
@mock.patch('scripts.service_installer.check_ambari_service_installed', return_value=False)
@mock.patch('__builtin__.raw_input', side_effect=['\n', '\n', 'v', 'y'])
def test_zeppelin_no_ambari_contact_continue(self, mock, mock2, mock3, mock4, mock5):
assert service_installer.install_zeppelin('../conf') == True
assert service_installer.install_zeppelin() == True


@mock.patch('scripts.service_installer.is_ambari_installed', return_value=True)
Expand All @@ -145,28 +145,28 @@ def test_zeppelin_no_ambari_contact_continue(self, mock, mock2, mock3, mock4, mo
@mock.patch('scripts.service_installer.check_ambari_service_installed', return_value=False)
@mock.patch('__builtin__.raw_input', side_effect=['\n', '\n', 'v', 'n'])
def test_zeppelin_no_ambari_contact_no_continue(self, mock, mock2, mock3, mock4, mock5):
assert service_installer.install_zeppelin('../conf') == False
assert service_installer.install_zeppelin() == False

class TestAmbariServiceCheck(unittest.TestCase):


@mock.patch('scripts.curl_client.CurlClient.make_request', side_effect=[['', ''], ['200 OK', '']])
@mock.patch('__builtin__.raw_input', side_effect=['\n', '\n', 'v', 'n'])
def test_ambari_check_good(self, mock, mock2):
conf = scripts.config.read_config('../conf/global-config.conf')['AMBARI']
conf = scripts.config.read_config('global-config.conf')['AMBARI']
assert service_installer.check_ambari_service_installed('ZEPPELIN', conf) == True

@mock.patch('scripts.curl_client.CurlClient.make_request', side_effect=[['200 OK', ''], ['200 OK', '']])
@mock.patch('__builtin__.raw_input', side_effect=['\n', '\n', 'v', 'n'])
def test_ambari_check_false(self, mock, mock2):
conf = scripts.config.read_config('../conf/global-config.conf')['AMBARI']
conf = scripts.config.read_config('global-config.conf')['AMBARI']
assert service_installer.check_ambari_service_installed('ZEPPELIN', conf) == True


@mock.patch('scripts.curl_client.CurlClient.make_request', side_effect=[['', ''],['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', ''], ['', '']])
@mock.patch('__builtin__.raw_input', side_effect=['', '', '', '', '', '', '', '', '', '', ''])
def test_ambari_check_many_attempts(self, mock, mock2):
conf = scripts.config.read_config('../conf/global-config.conf')['AMBARI']
conf = scripts.config.read_config('global-config.conf')['AMBARI']
assert service_installer.check_ambari_service_installed('ZEPPELIN', conf) == False


Expand Down Expand Up @@ -206,7 +206,6 @@ def test_nifi_check_is_good(self, mock, mock2, mock3, mock4, mock5):
@mock.patch('__builtin__.raw_input', side_effect=['\n', '\n', 'v', 'y'])
def test_nifi_no_ambari_contact_continue(self, mock, mock2, mock3, mock4, mock5):
assert service_installer.install_nifi('../conf') == True


@mock.patch('scripts.service_installer.is_ambari_installed', return_value=True)
@mock.patch('scripts.service_installer.is_hdp_select_installed', return_value=True)
Expand All @@ -215,39 +214,45 @@ def test_nifi_no_ambari_contact_continue(self, mock, mock2, mock3, mock4, mock5)
@mock.patch('__builtin__.raw_input', side_effect=['\n', '\n', 'v', 'n'])
def test_nifi_no_ambari_contact_no_continue(self, mock, mock2, mock3, mock4, mock5):
assert service_installer.install_nifi('../conf') == False



































class TestZeppelinAddNotebook(unittest.TestCase):

@mock.patch('scripts.curl_client.CurlClient.make_request', return_value=['201 Created', ''])
@mock.patch('os.path.isfile', return_value=True)
@mock.patch('os.listdir', return_value=['note1.json', 'note2.json', 'note3.json'])
def test_good(self, mock1, mock2, mock3):
assert (service_installer.add_zeppelin_notebooks())

@mock.patch('scripts.curl_client.CurlClient.make_request', return_value=['500 err', ''])
@mock.patch('os.path.isfile', return_value=True)
@mock.patch('os.listdir', return_value=['note1.json', 'note2.json', 'note3.json'])
def test_bad(self, mock1, mock2, mock3):
assert (not service_installer.add_zeppelin_notebooks())

@mock.patch('scripts.curl_client.CurlClient.make_request', return_value=['500 err', ''])
@mock.patch('os.path.isfile', return_value=True)
@mock.patch('os.listdir', return_value=['note1.json', 'note2.json', 'note3.xml'])
def test_mixed(self, mock1, mock2, mock3):
assert (not service_installer.add_zeppelin_notebooks())

@mock.patch('scripts.curl_client.CurlClient.make_request', side_effect=[['500 err', ''], ['201 Created', ''], ['201 Created', '']])
@mock.patch('os.path.isfile', return_value=True)
@mock.patch('os.listdir', return_value=['note1.json', 'note2.json', 'note3.xml'])
def test_mixed_response(self, mock1, mock2, mock3):
assert (not service_installer.add_zeppelin_notebooks())

@mock.patch('scripts.curl_client.CurlClient.make_request', side_effect=[['500 err', ''], ['201 Created', ''], ['201 Created', '']])
@mock.patch('os.path.isfile', return_value=True)
def test_post_notebook(self, mock1, mock2):

paths = ['note1.json', 'note2.json', 'note3.xml']
assert not service_installer.post_notebook(paths[0])

assert service_installer.post_notebook(paths[1])

assert service_installer.post_notebook(paths[2])