From f16f216bf6d4f7e33fcebc40be906e5eaa1d7e33 Mon Sep 17 00:00:00 2001 From: Kyle Kelley Date: Thu, 13 Nov 2014 17:04:20 -0600 Subject: [PATCH 01/11] Change matplotlib to install 1.3.1 from PyPI. --- attributes/default.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/attributes/default.rb b/attributes/default.rb index c9b27c7..0f9a7ea 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -164,7 +164,7 @@ "six==1.5.2", "scikit-learn==0.14.1", "pandas==0.12.0", - "https://downloads.sourceforge.net/project/matplotlib/matplotlib/matplotlib-1.3.1/matplotlib-1.3.1.tar.gz", + "matplotlib==1.3.1", "pygments==1.6", "readline==6.2.4.1", "nose==1.3.0", From 459d7de3974b7cb31d636d2e7b6f9935d88338ca Mon Sep 17 00:00:00 2001 From: Kyle Kelley Date: Mon, 5 Jan 2015 23:46:54 -0600 Subject: [PATCH 02/11] Remove nltk --- attributes/default.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/attributes/default.rb b/attributes/default.rb index 0f9a7ea..d5695fd 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -177,7 +177,6 @@ "statsmodels==0.5.0", "sympy==0.7.4.1", "scikit-image==0.9.3", - "nltk==2.0.4", "theano==0.6.0", "xlrd==0.9.2", "xlwt==0.7.5" From 930b88a28e41db05543880dd721739a34a655580 Mon Sep 17 00:00:00 2001 From: Benjamin Combourieu Date: Mon, 23 Feb 2015 18:27:10 +0100 Subject: [PATCH 03/11] Enabling customized notebook config --- attributes/default.rb | 6 ++++++ templates/default/ipython_notebook_config.py.erb | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/attributes/default.rb b/attributes/default.rb index d5695fd..7cc38fc 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -106,6 +106,12 @@ default[:ipynb][:NotebookApp][:base_kernel_url] = nil default[:ipynb][:NotebookApp][:webapp_settings][:static_url_prefix] = nil + +# Any additional configuration for Notebooks, to complete +# ipython_notebook_config.py ruby template +default[:ipynb][:NotebookApp][:additional_config] = nil + + ################################################################################ # Virtualenv ################################################################################ diff --git a/templates/default/ipython_notebook_config.py.erb b/templates/default/ipython_notebook_config.py.erb index c8b0604..fa66118 100644 --- a/templates/default/ipython_notebook_config.py.erb +++ b/templates/default/ipython_notebook_config.py.erb @@ -60,3 +60,11 @@ c.NotebookApp.password = '<%= node[:ipynb][:NotebookApp][:password_hash] %>' <% end %> c.NotebookApp.webapp_settings = {'static_url_prefix':'/static/'} + +# +# Adding whatever content you feel like to the notebook config file. You +# have to make sure it does not interfere with parameters already covered +# in ipython_notebook_config.py ruby template. +# + +<%= node[:ipynb][:NotebookApp][:additional_config] %> From 0ef7911933ef0c22da9a8899ff53af59f3812d1b Mon Sep 17 00:00:00 2001 From: davidski Date: Sat, 23 May 2015 07:37:31 -0700 Subject: [PATCH 04/11] Allow notebook_dir to take effect --- templates/default/ipython_notebook_config.py.erb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/templates/default/ipython_notebook_config.py.erb b/templates/default/ipython_notebook_config.py.erb index fa66118..b6d48f1 100644 --- a/templates/default/ipython_notebook_config.py.erb +++ b/templates/default/ipython_notebook_config.py.erb @@ -23,6 +23,11 @@ c.IPKernelApp.pylab = '<%= node[:ipynb][:NotebookApp][:pylab] %>' <% unless node[:ipynb][:proxy][:enable] %> <% unless node[:ipynb][:NotebookApp][:certfile].nil? %> +# Set notebook home directory +c.NotebookApp.notebook_dir = <%= node[:ipynb][:notebook_dir] %> +<% end %> +<% unless node[:ipynb][:notebook_dir].nil? %> + # SSL Certificate c.NotebookApp.certfile = '<%= node[:ipynb][:NotebookApp][:certfile] %>' <% end %> From 2087eb2d0bb78e2522c8723c9d1c0995f8c64155 Mon Sep 17 00:00:00 2001 From: davidski Date: Sat, 23 May 2015 08:16:51 -0700 Subject: [PATCH 05/11] Foodcritic cleanup --- .../default/ipython_notebook_config.py.erb | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/templates/default/ipython_notebook_config.py.erb b/templates/default/ipython_notebook_config.py.erb index b6d48f1..f580311 100644 --- a/templates/default/ipython_notebook_config.py.erb +++ b/templates/default/ipython_notebook_config.py.erb @@ -2,53 +2,53 @@ # vi: set ft=python : # -# Generated by Chef for <%= node[:ipynb][:linux_user] %> using the ipynb-cookbook +# Generated by Chef for <%= node['ipynb']['linux_user'] %> using the ipython-notebook-cookbook # # Find out more at # -# https://github.com/rgbkrk/ipynb-cookbook +# https://github.com/rgbkrk/ipython-notebook-cookbook # c = get_config() # Kernel config -<% unless node[:ipynb][:NotebookApp][:pylab].nil? %> +<% unless node['ipynb']['NotebookApp']['pylab'].nil? %> # Pre-load matplotlib and numpy for interactive use, selecting a particular # matplotlib backend and loop integration. # Choices: ['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'] -c.IPKernelApp.pylab = '<%= node[:ipynb][:NotebookApp][:pylab] %>' +c.IPKernelApp.pylab = '<%= node['ipynb']['NotebookApp']['pylab'] %>' <% end %> -<% unless node[:ipynb][:proxy][:enable] %> - <% unless node[:ipynb][:NotebookApp][:certfile].nil? %> +<% unless node['ipynb']['proxy']['enable'] %> + <% unless node['ipynb']['NotebookApp']['certfile'].nil? %> # Set notebook home directory -c.NotebookApp.notebook_dir = <%= node[:ipynb][:notebook_dir] %> +c.NotebookApp.notebook_dir = <%= node['ipynb']['notebook_dir'] %> <% end %> -<% unless node[:ipynb][:notebook_dir].nil? %> +<% unless node['ipynb']['notebook_dir'].nil? %> # SSL Certificate -c.NotebookApp.certfile = '<%= node[:ipynb][:NotebookApp][:certfile] %>' +c.NotebookApp.certfile = '<%= node['ipynb']['NotebookApp']['certfile'] %>' <% end %> <% end %> -<% unless node[:ipynb][:NotebookApp][:ip].nil? %> +<% unless node['ipynb']['NotebookApp']['ip'].nil? %> # The IP address the notebook server will listen on. # If set to '*', will listen on all interfaces. -c.NotebookApp.ip= '<%= node[:ipynb][:NotebookApp][:ip] %>' +c.NotebookApp.ip= '<%= node['ipynb']['NotebookApp']['ip'] %>' <% end %> -<% unless node[:ipynb][:NotebookApp][:port].nil? %> +<% unless node['ipynb']['NotebookApp']['port'].nil? %> # Port to host on (e.g. 8888, the default) -c.NotebookApp.port = <%= node[:ipynb][:NotebookApp][:port] %> +c.NotebookApp.port = <%= node['ipynb']['NotebookApp']['port'] %> <% end %> -<% unless node[:ipynb][:NotebookApp][:open_browser].nil? %> +<% unless node['ipynb']['NotebookApp']['open_browser'].nil? %> # Open browser (probably want False) -c.NotebookApp.open_browser = <%= node[:ipynb][:NotebookApp][:open_browser] %> +c.NotebookApp.open_browser = <%= node['ipynb']['NotebookApp']['open_browser'] %> <% end %> -<% unless node[:ipynb][:NotebookApp][:password_hash].nil? %> +<% unless node['ipynb']['NotebookApp']['password_hash'].nil? %> # # Password created using IPython.lib.passwd @@ -61,7 +61,7 @@ c.NotebookApp.open_browser = <%= node[:ipynb][:NotebookApp][:open_browser] %> # Verify password: # Out[2]: 'sha1:d2fb9930b3ed:8facdbc05c08e1affbc8424a0717c2b21d10f4a3' # -c.NotebookApp.password = '<%= node[:ipynb][:NotebookApp][:password_hash] %>' +c.NotebookApp.password = '<%= node['ipynb']['NotebookApp']['password_hash'] %>' <% end %> c.NotebookApp.webapp_settings = {'static_url_prefix':'/static/'} @@ -72,4 +72,4 @@ c.NotebookApp.webapp_settings = {'static_url_prefix':'/static/'} # in ipython_notebook_config.py ruby template. # -<%= node[:ipynb][:NotebookApp][:additional_config] %> +<%= node['ipynb']['NotebookApp']['additional_config'] %> From b4da3d53a02145997d042cf19ecd49ecead71887 Mon Sep 17 00:00:00 2001 From: davidski Date: Sat, 23 May 2015 09:07:39 -0700 Subject: [PATCH 06/11] Foodcritic cleanup --- templates/default/ipython_notebook_config.py.erb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/templates/default/ipython_notebook_config.py.erb b/templates/default/ipython_notebook_config.py.erb index f580311..a3535c7 100644 --- a/templates/default/ipython_notebook_config.py.erb +++ b/templates/default/ipython_notebook_config.py.erb @@ -20,13 +20,14 @@ c = get_config() # Choices: ['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'] c.IPKernelApp.pylab = '<%= node['ipynb']['NotebookApp']['pylab'] %>' <% end %> -<% unless node['ipynb']['proxy']['enable'] %> - <% unless node['ipynb']['NotebookApp']['certfile'].nil? %> +<% unless node['ipynb']['notebook_dir'].nil? %> # Set notebook home directory c.NotebookApp.notebook_dir = <%= node['ipynb']['notebook_dir'] %> <% end %> -<% unless node['ipynb']['notebook_dir'].nil? %> + +<% unless node['ipynb']['proxy']['enable'] %> + <% unless node['ipynb']['NotebookApp']['certfile'].nil? %> # SSL Certificate c.NotebookApp.certfile = '<%= node['ipynb']['NotebookApp']['certfile'] %>' From 146b42a7e24c4c034320e58c78d8f70a2dbc099e Mon Sep 17 00:00:00 2001 From: davidski Date: Sat, 23 May 2015 09:51:40 -0700 Subject: [PATCH 07/11] Correct notebook homedir param name --- templates/default/ipython_notebook_config.py.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/default/ipython_notebook_config.py.erb b/templates/default/ipython_notebook_config.py.erb index a3535c7..e307628 100644 --- a/templates/default/ipython_notebook_config.py.erb +++ b/templates/default/ipython_notebook_config.py.erb @@ -23,7 +23,7 @@ c.IPKernelApp.pylab = '<%= node['ipynb']['NotebookApp']['pylab'] %>' <% unless node['ipynb']['notebook_dir'].nil? %> # Set notebook home directory -c.NotebookApp.notebook_dir = <%= node['ipynb']['notebook_dir'] %> +c.FileNotebookManager.notebook_dir = u'<%= node['ipynb']['notebook_dir'] %>' <% end %> <% unless node['ipynb']['proxy']['enable'] %> From 700c31e264da1e485ba9e1f54f2f78bfde554b8a Mon Sep 17 00:00:00 2001 From: Kyle Kelley Date: Mon, 22 Jun 2015 12:53:17 -0500 Subject: [PATCH 08/11] Upgrade to 3.2.0 2.x-3.1 had a security vulnerability: http://seclists.org/oss-sec/2015/q2/779 --- attributes/default.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/attributes/default.rb b/attributes/default.rb index 7cc38fc..3e5da34 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -190,7 +190,7 @@ # Let users configure exactly what version of IPython they are going to pull (from git, PyPI, etc.) # Most of the attributes, configuration, etc. rely on IPython 1.0 so be wary if for some reason you want to use 0.x releases. -default[:ipynb][:ipython_package] = "ipython[notebook]==2.2.0" +default[:ipynb][:ipython_package] = "ipython[notebook]==3.2.0" # Additional packages to install into the same virtualenv as the IPython notebook default[:ipynb][:extra_packages] = [] From 14b064ee6c034396603988845da65e3db686806c Mon Sep 17 00:00:00 2001 From: "David F. Severski" Date: Sat, 24 Dec 2016 12:56:06 -0800 Subject: [PATCH 09/11] Update packages and python version for Ubuntu 16.04 LTS --- attributes/default.rb | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/attributes/default.rb b/attributes/default.rb index 7cc38fc..a027906 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -120,7 +120,8 @@ default[:ipynb][:virtenv] = nil #File.join(default[:ipynb][:home_dir], ".ipyvirt") # Version of Python to use -default[:ipynb][:py_version] = "python2.7" +default[:ipynb][:py_version] = "python3.5" +default[:ipynb][:py_version] = "python2.7" if node['platform_version'] == '16.04' ################################################################################ # Software Stack (system packages) @@ -128,6 +129,16 @@ # System packages, at least for Ubuntu (naming may change) case node['platform_version'] +when '16.04' + default[:ipynb][:system_packages] = %w( + build-essential libcurl4-openssl-dev libssl-dev zlib1g-dev libpcre3-dev + gfortran libblas-dev liblapack-dev libncurses5-dev libatlas-base-dev + libscalapack-openmpi1 libscalapack-pvm1 python-pil-doc python-pil-dbg + libjpeg-turbo8 libjpeg8 python-imaging libpng12-0 libpng12-dev + libfreetype6 libfreetype6-dev python-pycurl-dbg git-core + cython libhdf5-serial-dev python-egenix-mxdatetime vim python-numpy + python-scipy pandoc +) when '14.04' default[:ipynb][:system_packages] = %w( build-essential libcurl4-openssl-dev libssl-dev zlib1g-dev libpcre3-dev From c2c2fff35dc89106eab763e1af5561eaf4814a9e Mon Sep 17 00:00:00 2001 From: "David F. Severski" Date: Sat, 31 Dec 2016 15:59:22 -0800 Subject: [PATCH 10/11] Use Jupyter as default notebook server. Update cookbook dependencies. Move to test-kitchen and inspec for testing. --- .gitignore | 2 + .kitchen.yml | 61 +++++ Berksfile | 24 +- Vagrantfile | 91 ------- attributes/default.rb | 234 ++++++++++-------- chefignore | 4 + libraries/ipython_utils.rb | 16 +- metadata.rb | 16 +- providers/mathjax.rb | 47 ---- providers/profile.rb | 30 +-- recipes/default.rb | 109 ++++---- recipes/proxy.rb | 63 ++--- recipes/virtenv_launch.rb | 106 ++++---- resources/mathjax.rb | 33 --- resources/profile.rb | 13 +- ....py.erb => jupyter_notebook_config.py.erb} | 26 +- test/integration/default/jupyter_service.rb | 16 ++ 17 files changed, 384 insertions(+), 507 deletions(-) create mode 100644 .kitchen.yml delete mode 100644 Vagrantfile delete mode 100644 providers/mathjax.rb delete mode 100644 resources/mathjax.rb rename templates/default/{ipython_notebook_config.py.erb => jupyter_notebook_config.py.erb} (73%) create mode 100644 test/integration/default/jupyter_service.rb diff --git a/.gitignore b/.gitignore index 45b891c..c414043 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ Gemfile.lock bin/* .bundle/* +*.bak +.kitchen/ \ No newline at end of file diff --git a/.kitchen.yml b/.kitchen.yml new file mode 100644 index 0000000..dc431e3 --- /dev/null +++ b/.kitchen.yml @@ -0,0 +1,61 @@ +--- +driver: + name: vagrant + network: + - ["private_network", ip: "33.33.33.10"] + - ["forwarded_port", {guest: 8888, host: 9999}] +platforms: + - name: ubuntu-16.04 + - name: ubuntu-14.04 +provisioner: + name: chef_zero +suites: + - attributes: + ipynb: + NotebookApp: + password: test + scientific_stack: [] + ssl_certificate: /etc/nginx/ssl.pem + ssl_certificate_key: /etc/nginx/ssl.key + ssl_certificate_key_text: |- + -----BEGIN RSA PRIVATE KEY----- + MIICXQIBAAKBgQDKDv8EmwzlrhoN7XknVNDyZFMC3eQl60fSrNgjYjMojMmNlrRx + p770h5Y9dosEuQXuXMbYyvyQpQemDWiQEt6rkGhOB5lZ9NheWn6nnW+9YBbtwkqz + ZuAoq6asuvH4faXivg6d8Qxt0xa+g3vFUNVzKBLoRziYFN4NEO+gxrXbXwIDAQAB + AoGBAIJMhVtc+UYrrZWJq/UXFt8YnwdcO8HQJbLPz1mR+9eMYnUx2A7q05Mw1Euy + ZBeZkR+TKI+o5pIIOhR01RcDdB8dPtoVCgiDSyb/kzhqnEvY/8IvvHdvGQU2V5q3 + 6NVISp/SIRUuFxoTuPq5tF0cvPYSp4U+BBFavnXwe1y9KUSxAkEA6gs2rDyMVU7K + 0yY+pzWM6/OdNKPWYRCBeCRxo1d2k4xlkoPOq8xVm5+RyNq9NBGWkUSROz6zOuwH + swExKq3sswJBAN0DoHMks6o/vw2Z86FJEEffWuDXRHZeMfgaug8vuDHLzrkZcUzb + WJcbNTF1H1FeF3ITevt98CZOhrZHCXcwhKUCQQDorCc5SaR1trQ7AB1vW/RyKimS + SIL60k70Ir76lRwkCYJ9Cx5ueuBsq1FibduFJSsb1h/P10CVhksNMVUwyeGzAkA9 + YVl5QPMo0CVmSKBR5bHA1DYwBXj9CrID/qA3wX/9TGXwIDHIL47OAH9oaee1uFT4 + mJJqMBK3AM4G53mogXAFAkBSpcRbCXlWBUJjGiE9qrpaqrDhncNhMA5zqxkxmGEF + WfBxaOjp9wsQZZHX+bSQLp92WjW0Uq712dtL7CVOWqxb + -----END RSA PRIVATE KEY----- + ssl_certificate_text: |- + -----BEGIN CERTIFICATE----- + MIICmDCCAgGgAwIBAgIJAONj1DIGs9lkMA0GCSqGSIb3DQEBBQUAMD0xCzAJBgNV + BAYTAlVTMQswCQYDVQQIEwJUWDEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ + dHkgTHRkMB4XDTEzMDgxOTIwNDE0NloXDTE0MDgxOTIwNDE0NlowPTELMAkGA1UE + BhMCVVMxCzAJBgNVBAgTAlRYMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0 + eSBMdGQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMoO/wSbDOWuGg3teSdU + 0PJkUwLd5CXrR9Ks2CNiMyiMyY2WtHGnvvSHlj12iwS5Be5cxtjK/JClB6YNaJAS + 3quQaE4HmVn02F5afqedb71gFu3CSrNm4Cirpqy68fh9peK+Dp3xDG3TFr6De8VQ + 1XMoEuhHOJgU3g0Q76DGtdtfAgMBAAGjgZ8wgZwwHQYDVR0OBBYEFKJEzyGWKl47 + WecMx/gocolKLN1IMG0GA1UdIwRmMGSAFKJEzyGWKl47WecMx/gocolKLN1IoUGk + PzA9MQswCQYDVQQGEwJVUzELMAkGA1UECBMCVFgxITAfBgNVBAoTGEludGVybmV0 + IFdpZGdpdHMgUHR5IEx0ZIIJAONj1DIGs9lkMAwGA1UdEwQFMAMBAf8wDQYJKoZI + hvcNAQEFBQADgYEAUxagzwBN/fCJlKh1eIdO/oWBqtt9Ca70VSylD0WJrtgznreG + fZJ4bEzYsCAsWcQowSmEkzQeXzB60EUT3I09SbyFe7+JD+/CGiBfET42ABGwGNUV + dE3w7J7Coc46rYXAqMg05hBYrOe43nra2RHTFxQr5V+oDLMcZuPI2Ozo4e4= + -----END CERTIFICATE----- + name: default + run_list: + - "recipe[apt]" + - "recipe[yum]" + - "recipe[ipynb::default]" + - "recipe[ipynb::virtenv_launch]" + - "recipe[ipynb::proxy]" + verifier: + name: inspec diff --git a/Berksfile b/Berksfile index 45a740d..34fea21 100644 --- a/Berksfile +++ b/Berksfile @@ -1,25 +1,3 @@ -#!/usr/bin/env ruby - -site :opscode - -# Locking version of the python cookbook that uses setuptools instead of distribute -cookbook 'python', - :git => 'https://github.com/comandrei/python.git', - :ref => '2cc384b5d996ca8b701826af265334bda40d0201' -# :git => 'https://github.com/poise/python.git', -# :ref => '8ce88cd17b0d6c64e948f1580815b5884b3c0f26' - -cookbook 'apt' -cookbook 'yum' - -cookbook 'runit' - -cookbook 'nginx', - :git => 'https://github.com/opscode-cookbooks/nginx.git', - :ref => 'd7a41ce15b30f91df95195b213d95bb9b3a6c4c3' - -cookbook 'supervisor', - :git => 'https://github.com/poise/supervisor.git', - :ref => 'ffd88b59e3df97613b9ecfd53d489f6715551755' +source 'https://supermarket.chef.io' metadata diff --git a/Vagrantfile b/Vagrantfile deleted file mode 100644 index b558942..0000000 --- a/Vagrantfile +++ /dev/null @@ -1,91 +0,0 @@ -# -*- mode: ruby -*- -# vi: set ft=ruby : - -Vagrant.configure("2") do |config| - - # Name the box for Vagrant - config.vm.define :IPyBox - - config.vm.provider "virtualbox" do |ipybox| - ipybox.name = "IPyBox" - end - - config.vm.hostname = "ipynb-cookbook-berkshelf" - - config.omnibus.chef_version = "11.12.8" - - config.vm.box = "ubuntu-14.04" - config.vm.box_url = "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_#{config.vm.box}_chef-provisionerless.box" - - # Forward the default 8888 port for the IPython notebook, - # keeping the port different on the host box in case the user - # is running the IPython notebook locally - config.vm.network :private_network, ip: "33.33.33.10" - config.vm.network :forwarded_port, guest: 80, host: 9999 - - # Enabling the Berkshelf plugin. To enable this globally, add this configuration - # option to your ~/.vagrant.d/Vagrantfile file - config.berkshelf.enabled = true - - - config.vm.provision :chef_solo do |chef| - - chef.log_level = :debug - - chef.json = { - :ipynb => { - :NotebookApp => { - :password => "test", - }, - :ssl_certificate => "/etc/nginx/ssl.pem", - :ssl_certificate_key => "/etc/nginx/ssl.key", - # Note: Don't use this key in production -- this is just a vagrant testing key - :ssl_certificate_key_text => <<-eos, ------BEGIN RSA PRIVATE KEY----- -MIICXQIBAAKBgQDKDv8EmwzlrhoN7XknVNDyZFMC3eQl60fSrNgjYjMojMmNlrRx -p770h5Y9dosEuQXuXMbYyvyQpQemDWiQEt6rkGhOB5lZ9NheWn6nnW+9YBbtwkqz -ZuAoq6asuvH4faXivg6d8Qxt0xa+g3vFUNVzKBLoRziYFN4NEO+gxrXbXwIDAQAB -AoGBAIJMhVtc+UYrrZWJq/UXFt8YnwdcO8HQJbLPz1mR+9eMYnUx2A7q05Mw1Euy -ZBeZkR+TKI+o5pIIOhR01RcDdB8dPtoVCgiDSyb/kzhqnEvY/8IvvHdvGQU2V5q3 -6NVISp/SIRUuFxoTuPq5tF0cvPYSp4U+BBFavnXwe1y9KUSxAkEA6gs2rDyMVU7K -0yY+pzWM6/OdNKPWYRCBeCRxo1d2k4xlkoPOq8xVm5+RyNq9NBGWkUSROz6zOuwH -swExKq3sswJBAN0DoHMks6o/vw2Z86FJEEffWuDXRHZeMfgaug8vuDHLzrkZcUzb -WJcbNTF1H1FeF3ITevt98CZOhrZHCXcwhKUCQQDorCc5SaR1trQ7AB1vW/RyKimS -SIL60k70Ir76lRwkCYJ9Cx5ueuBsq1FibduFJSsb1h/P10CVhksNMVUwyeGzAkA9 -YVl5QPMo0CVmSKBR5bHA1DYwBXj9CrID/qA3wX/9TGXwIDHIL47OAH9oaee1uFT4 -mJJqMBK3AM4G53mogXAFAkBSpcRbCXlWBUJjGiE9qrpaqrDhncNhMA5zqxkxmGEF -WfBxaOjp9wsQZZHX+bSQLp92WjW0Uq712dtL7CVOWqxb ------END RSA PRIVATE KEY----- -eos - :ssl_certificate_text => <<-eos, ------BEGIN CERTIFICATE----- -MIICmDCCAgGgAwIBAgIJAONj1DIGs9lkMA0GCSqGSIb3DQEBBQUAMD0xCzAJBgNV -BAYTAlVTMQswCQYDVQQIEwJUWDEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ -dHkgTHRkMB4XDTEzMDgxOTIwNDE0NloXDTE0MDgxOTIwNDE0NlowPTELMAkGA1UE -BhMCVVMxCzAJBgNVBAgTAlRYMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0 -eSBMdGQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMoO/wSbDOWuGg3teSdU -0PJkUwLd5CXrR9Ks2CNiMyiMyY2WtHGnvvSHlj12iwS5Be5cxtjK/JClB6YNaJAS -3quQaE4HmVn02F5afqedb71gFu3CSrNm4Cirpqy68fh9peK+Dp3xDG3TFr6De8VQ -1XMoEuhHOJgU3g0Q76DGtdtfAgMBAAGjgZ8wgZwwHQYDVR0OBBYEFKJEzyGWKl47 -WecMx/gocolKLN1IMG0GA1UdIwRmMGSAFKJEzyGWKl47WecMx/gocolKLN1IoUGk -PzA9MQswCQYDVQQGEwJVUzELMAkGA1UECBMCVFgxITAfBgNVBAoTGEludGVybmV0 -IFdpZGdpdHMgUHR5IEx0ZIIJAONj1DIGs9lkMAwGA1UdEwQFMAMBAf8wDQYJKoZI -hvcNAQEFBQADgYEAUxagzwBN/fCJlKh1eIdO/oWBqtt9Ca70VSylD0WJrtgznreG -fZJ4bEzYsCAsWcQowSmEkzQeXzB60EUT3I09SbyFe7+JD+/CGiBfET42ABGwGNUV -dE3w7J7Coc46rYXAqMg05hBYrOe43nra2RHTFxQr5V+oDLMcZuPI2Ozo4e4= ------END CERTIFICATE----- -eos - # Make boot up quicker when simply testing the notebook - #:scientific_stack => [], - } - } - - chef.run_list = [ - "recipe[apt]", - "recipe[yum]", - "recipe[ipynb::default]", - "recipe[ipynb::virtenv_launch]", - "recipe[ipynb::proxy]" - ] - end -end diff --git a/attributes/default.rb b/attributes/default.rb index 8a0e598..5231d29 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -8,45 +8,57 @@ # Server side configuration ################################################################################ -# linux user and group for the system IPython is being deployed to -default[:ipynb][:linux_user] = "ipynb" -default[:ipynb][:linux_group] = "ipynb" +# user and group for the system IPython is being deployed to +default['ipynb']['linux_user'] = 'ipynb' +default['ipynb']['linux_group'] = 'ipynb' # Home directory for the system user -default[:ipynb][:home_dir] = nil #File.join("/home/", default[:ipynb][:linux_user]) +default['ipynb']['home_dir'] = nil # File.join('/home/', default['ipynb']['linux_user']) # Spot to store the notebook files -default[:ipynb][:notebook_dir] = nil #File.join(default[:ipynb][:home_dir], - # "notebooks") +default['ipynb']['notebook_dir'] = nil # File.join(default[:ipynb][:home_dir], +# "notebooks") -default[:supervisor][:version] = "3.0" - -# Supervisord service name -default[:ipynb][:service_name] = "ipynb" +# Service name +default['ipynb']['service_name'] = 'jupyter' # IPython profile -default[:ipynb][:profile_name] = "cooked" +default['ipynb']['profile_name'] = 'cooked' + +default['ipynb']['proxy']['enable'] = true +default['ipynb']['proxy']['hostname'] = fqdn +default['ipynb']['proxy']['alias_hostnames'] = [] + +default['nginx']['default_site_enabled'] = false + +default['nginx']['version'] = '1.10.2' +default['nginx']['source']['version'] = '1.10.2' +# The Chef checksum of a binary is determined by: shasum -a 256 FILE_NAME +default['nginx']['source']['checksum'] = '1045AC4987A396E2FA5D0011DAF8987B612DD2F05181B67507DA68CBE7D765C2' +default['nginx']['source']['prefix'] = "/opt/nginx-#{node['nginx']['source']['version']}" +default['nginx']['source']['url'] = "http://nginx.org/download/nginx-#{node['nginx']['source']['version']}.tar.gz" +default['nginx']['source']['sbin_path'] = "#{node['nginx']['source']['prefix']}/sbin/nginx" -default[:ipynb][:proxy][:enable] = true -default[:ipynb][:proxy][:hostname] = fqdn -default[:ipynb][:proxy][:alias_hostnames] = [] +default['nginx']['source']['default_configure_flags'] = [ + "--prefix=#{node['nginx']['source']['prefix']}", + "--conf-path=#{node['nginx']['dir']}/nginx.conf", + "--sbin-path=#{node['nginx']['source']['sbin_path']}", +] +node.default['nginx']['init_style'] = 'runit' ################################################################################ # IPython Notebook runtime configuration ################################################################################ -# Pick how plots are done -default[:ipynb][:NotebookApp][:pylab] = 'inline' - # IP to host on, defaults to all interfaces -default[:ipynb][:NotebookApp][:ip] = '127.0.0.1' +default['ipynb']['NotebookApp']['ip'] = '127.0.0.1' # Port to host on -default[:ipynb][:NotebookApp][:port] = 8888 +default['ipynb']['NotebookApp']['port'] = 8888 # Choose whether to open a browser, default is server mode (no browser run on # server -- interact on client) -default[:ipynb][:NotebookApp][:open_browser] = 'False' +default['ipynb']['NotebookApp']['open_browser'] = 'False' # SSL Certificate file (private), should be the absolute path of the PEM file # you want to use. @@ -60,16 +72,16 @@ # # http://arstechnica.com/security/news/2009/12/how-to-get-set-with-a- # -default[:ipynb][:ssl_certificate] = nil -default[:ipynb][:ssl_certificate_text] = nil -default[:ipynb][:ssl_certificate_key] = nil -default[:ipynb][:ssl_certificate_key_text] = nil +default['ipynb']['ssl_certificate'] = nil +default['ipynb']['ssl_certificate_text'] = nil +default['ipynb']['ssl_certificate_key'] = nil +default['ipynb']['ssl_certificate_key_text'] = nil -# Hashed Password with Salt, Algorithm for accessing the IPython Notebook +# Hashed Password with Salt, Algorithm for accessing the Jupyter Notebook # -# You can generate one using IPython.lib.passwd +# You can generate one using notebook.auth.passwd # -# In [1]: from IPython.lib import passwd +# In [1]: from notebook.auth import passwd # # In [2]: passwd() # Enter password: @@ -97,73 +109,81 @@ # Default shown here is "IPassword" (without the quotes) # 'sha1:f918d238efbd:4a250470288eb6a41f5df648a39f82606cbd33dd' # -default[:ipynb][:NotebookApp][:password_hash] = nil -default[:ipynb][:NotebookApp][:password] = nil +default['ipynb']['NotebookApp']['password_hash'] = nil +# Token for authenticating first connections to the server +# Only used if password_hash is set to nil +# Setting both password_hash and token to nil disables auth +# THIS IS NOT ADVISED! +default['ipynb']['NotebookApp']['token'] = 'IPassword' # Landing page settings -default[:ipynb][:NotebookApp][:base_project_url] = nil -default[:ipynb][:NotebookApp][:base_kernel_url] = nil -default[:ipynb][:NotebookApp][:webapp_settings][:static_url_prefix] = nil - +default['ipynb']['NotebookApp']['base_project_url'] = nil +default['ipynb']['NotebookApp']['base_kernel_url'] = nil +default['ipynb']['NotebookApp']['webapp_settings']['static_url_prefix'] = nil # Any additional configuration for Notebooks, to complete -# ipython_notebook_config.py ruby template -default[:ipynb][:NotebookApp][:additional_config] = nil - +# jupyter_notebook_config.py ruby template +default['ipynb']['NotebookApp']['additional_config'] = nil ################################################################################ # Virtualenv ################################################################################ # Where to store the virtual environment IPython runs in -default[:ipynb][:virtenv] = nil #File.join(default[:ipynb][:home_dir], ".ipyvirt") +default['ipynb']['virtenv'] = nil # File.join(default['ipynb']['home_dir'], '.ipyvirt') # Version of Python to use -default[:ipynb][:py_version] = "python3.5" -default[:ipynb][:py_version] = "python2.7" if node['platform_version'] == '16.04' +default['ipynb']['py_version'] = case node['platform_version'].to_f + when 16.04 + '3.5' + when 14.04 + '3.4' + else + '3.5' + end ################################################################################ # Software Stack (system packages) ################################################################################ # System packages, at least for Ubuntu (naming may change) -case node['platform_version'] -when '16.04' - default[:ipynb][:system_packages] = %w( - build-essential libcurl4-openssl-dev libssl-dev zlib1g-dev libpcre3-dev - gfortran libblas-dev liblapack-dev libncurses5-dev libatlas-base-dev - libscalapack-openmpi1 libscalapack-pvm1 python-pil-doc python-pil-dbg - libjpeg-turbo8 libjpeg8 python-imaging libpng12-0 libpng12-dev - libfreetype6 libfreetype6-dev python-pycurl-dbg git-core - cython libhdf5-serial-dev python-egenix-mxdatetime vim python-numpy - python-scipy pandoc -) -when '14.04' - default[:ipynb][:system_packages] = %w( - build-essential libcurl4-openssl-dev libssl-dev zlib1g-dev libpcre3-dev - gfortran libblas-dev libblas3gf liblapack3gf liblapack-dev libncurses5-dev - libatlas-dev libatlas-base-dev libscalapack-mpi1 libscalapack-pvm1 - liblcms-utils python-imaging-doc python-imaging-dbg - libamd2.3.1 libjpeg-turbo8 libjpeg8 liblcms1 libumfpack5.6.2 python-imaging - libpng12-0 libpng12-dev libfreetype6 libfreetype6-dev - libcurl4-gnutls-dev python-pycurl-dbg git-core - cython libhdf5-7 libhdf5-serial-dev - python-egenix-mxdatetime vim python-numpy python-scipy pandoc - ) -else - default[:ipynb][:system_packages] = %w( - build-essential libcurl4-openssl-dev libssl-dev zlib1g-dev libpcre3-dev - gfortran libblas-dev libblas3gf liblapack3gf liblapack-dev libncurses5-dev - libatlas-dev libatlas-base-dev libscalapack-mpi1 libscalapack-pvm1 - liblcms-utils python-imaging-doc python-imaging-dbg - libamd2.2.0 libjpeg-turbo8 libjpeg8 liblcms1 libumfpack5.4.0 python-imaging - libpng12-0 libpng12-dev libfreetype6 libfreetype6-dev - libcurl4-gnutls-dev python-pycurl-dbg git-core - cython libhdf5-7 libhdf5-serial-dev - python-egenix-mxdatetime vim python-numpy python-scipy pandoc - ) -end +default['ipynb']['system_packages'] = case node['platform_version'].to_f + when 16.04 + %w( + libcurl4-openssl-dev libssl-dev zlib1g-dev libpcre3-dev + gfortran libblas-dev liblapack-dev libncurses5-dev + libatlas-base-dev libscalapack-openmpi1 libscalapack-pvm1 + libjpeg-turbo8 libjpeg8 + libpng12-0 libpng12-dev + libfreetype6 libfreetype6-dev git-core + libhdf5-serial-dev pandoc + ) + when 14.04 + %w( + libcurl4-openssl-dev libssl-dev zlib1g-dev libpcre3-dev + gfortran libblas-dev libblas3gf liblapack3gf liblapack-dev libncurses5-dev + libatlas-dev libatlas-base-dev libscalapack-mpi1 libscalapack-pvm1 + liblcms-utils + libamd2.3.1 libjpeg-turbo8 libjpeg8 liblcms1 libumfpack5.6.2 + libpng12-0 libpng12-dev libfreetype6 libfreetype6-dev + git-core + libhdf5-7 libhdf5-serial-dev + pandoc + ) + else + %w( + libcurl4-openssl-dev libssl-dev zlib1g-dev libpcre3-dev + gfortran libblas-dev libblas3gf liblapack3gf liblapack-dev libncurses5-dev + libatlas-dev libatlas-base-dev libscalapack-mpi1 libscalapack-pvm1 + liblcms-utils + libamd2.2.0 libjpeg-turbo8 libjpeg8 liblcms1 libumfpack5.4.0 + libpng12-0 libpng12-dev libfreetype6 libfreetype6-dev + git-core + libhdf5-7 libhdf5-serial-dev + pandoc + ) + end ################################################################################ # Software Stack (pip installs) @@ -172,36 +192,38 @@ # The scientific computing stack, installed in order # Note that numpy must be first and the dependencies for matplotlib also have # to start first due to the way numpy+matplotlib are packaged -default[:ipynb][:scientific_stack] = ["numpy==1.8.0", - "freetype-py==0.4.1", - "pillow==2.3.0", - "scipy==0.13.2", - "python-dateutil", - "pytz==2013b", - "six==1.5.2", - "scikit-learn==0.14.1", - "pandas==0.12.0", - "matplotlib==1.3.1", - "pygments==1.6", - "readline==6.2.4.1", - "nose==1.3.0", - "pexpect==3.0", - "cython==0.19.2", - "networkx==1.8.1", - "numexpr==2.2.2", - "tables==3.0.0", - "patsy==0.2.1", - "statsmodels==0.5.0", - "sympy==0.7.4.1", - "scikit-image==0.9.3", - "theano==0.6.0", - "xlrd==0.9.2", - "xlwt==0.7.5" - ] - -# Let users configure exactly what version of IPython they are going to pull (from git, PyPI, etc.) -# Most of the attributes, configuration, etc. rely on IPython 1.0 so be wary if for some reason you want to use 0.x releases. -default[:ipynb][:ipython_package] = "ipython[notebook]==3.2.0" +default['ipynb']['scientific_stack'] = { 'numpy' => nil, + 'freetype-py' => '1.0.2', + 'pillow' => '4.0.0', + 'scipy' => '0.18.1', + 'python-dateutil' => nil, + 'pytz' => '2016.10', + 'six' => '1.10.0', + 'scikit-learn' => '0.18.1', + 'pandas' => '0.19.2', + 'matplotlib' => '1.5.3', + 'pygments' => '2.1.3', + 'readline' => '6.2.4.1', + 'nose' => '1.3.7', + 'pexpect' => '4.2.1', + 'cython' => '0.25.2', + 'networkx' => '1.11', + 'numexpr' => '2.6.1', + 'tables' => '3.3.0', + 'patsy' => '0.4.1', + 'statsmodels' => '0.6.1', + 'sympy' => '1.0', + 'scikit-image' => '0.12.3', + 'theano' => '0.8.2', + 'xlrd' => '1.0.0', + 'xlwt' => '1.1.2', + } + +# Let users configure exactly what version of Jupyter they are going to pull (from git, PyPI, etc.) +# Most of the attributes, configuration, etc. rely on Jupyter 4.x so be wary on changing +# Note that we default to the jupyter meta-package, which is jupyter1.0.0 +default['ipynb']['ipython_package'] = 'jupyter' +default['ipynb']['ipython_package_version'] = nil # Additional packages to install into the same virtualenv as the IPython notebook -default[:ipynb][:extra_packages] = [] +default['ipynb']['extra_packages'] = {} diff --git a/chefignore b/chefignore index a6de142..70cceef 100644 --- a/chefignore +++ b/chefignore @@ -94,3 +94,7 @@ Vagrantfile # Travis # ########## .travis.yml + +# Test-Kitchen # +################ +.kitchen \ No newline at end of file diff --git a/libraries/ipython_utils.rb b/libraries/ipython_utils.rb index d845bfe..a5b3f78 100644 --- a/libraries/ipython_utils.rb +++ b/libraries/ipython_utils.rb @@ -5,14 +5,12 @@ require 'securerandom' module IPythonAuth - def IPythonAuth.ipython_hash(password) + def self.ipython_hash(password) + hash_alg = Digest::SHA512 + hash_name = 'sha512' - hash_alg = Digest::SHA512 - hash_name = 'sha512' - - salt = SecureRandom.hex(6) - password_hash = hash_alg.hexdigest(password + salt) - return [hash_name, salt, password_hash].join(":") - end + salt = SecureRandom.hex(6) + password_hash = hash_alg.hexdigest(password + salt) + [hash_name, salt, password_hash].join(':') + end end - diff --git a/metadata.rb b/metadata.rb index 1c888aa..1174196 100644 --- a/metadata.rb +++ b/metadata.rb @@ -5,11 +5,15 @@ description 'Installs/Configures IPython Notebook' long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) version '1.1.0' +source_url 'https://github.com/rgbkrk/ipython-notebook-cookbook' if respond_to?(:source_url) +issues_url 'https://github.com/rgbkrk/ipython-notebook-cookbook/issues' if respond_to?(:issues_url) +chef_version '>= 12.1' -depends "python" -depends "yum", ">= 2.3.0" -depends "apt", ">= 2.0.0" -depends "supervisor", ">= 0.4.5" -depends "nginx", ">= 1.7.0" +depends 'poise-python', '~> 1.5' +depends 'poise-service', '~> 1.4.2' +depends 'apt', '~> 2.2' +depends 'build-essential', '>= 2' +# depends 'nginx', '~> 1.8' +depends 'nginx', '~> 2.7' -supports 'ubuntu' +supports 'ubuntu', '>= 14.04' diff --git a/providers/mathjax.rb b/providers/mathjax.rb deleted file mode 100644 index 0883c7d..0000000 --- a/providers/mathjax.rb +++ /dev/null @@ -1,47 +0,0 @@ -# -# Author:: Kyle Kelley -# Cookbook Name:: ipynb -# Provider:: mathjax -# -# Copyright:: 2013, Rackspace -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -action :create do - Chef::Log.info("Installing mathjax to\"#{new_resource.install_dir}\" for #{new_resource.owner}") - Chef::Log.info("Using IPython at #{new_resource.ipython_path}") - install_mathjax(new_resource.install_dir, new_resource.ipython_path, new_resource.owner) -end - -def install_mathjax(install_dir, ipython_path, owner) - - python "install_mathjax" do - user owner - group owner - cwd node[:ipynb][:home_dir] - - environment "HOME" => node[:ipynb][:home_dir], - "SHELL" => "/bin/bash", - "USER" => node[:ipynb][:linux_user], - "PATH" => "#{node[:ipynb][:virtenv]}/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games", - "VIRTUAL_ENV" => "#{node[:ipynb][:virtenv]}" - - code <<-EOH -from IPython.external.mathjax import install_mathjax -install_mathjax(replace=True, dest='#{install_dir}') - EOH - end - -end - diff --git a/providers/profile.rb b/providers/profile.rb index 9400564..6a97edc 100644 --- a/providers/profile.rb +++ b/providers/profile.rb @@ -19,21 +19,21 @@ # action :create do - Chef::Log.info("Creating profile \"#{new_resource.name}\" for #{new_resource.owner}") - Chef::Log.info("IPython path is at #{new_resource.ipython_path}") - Chef::Log.info("IPython settings are at #{new_resource.ipython_settings_dir}") - create_profile(new_resource.ipython_path, new_resource.owner, - new_resource.name, new_resource.ipython_settings_dir) + Chef::Log.info("Creating profile \"#{new_resource.name}\" for #{new_resource.owner}") + Chef::Log.info("IPython path is at #{new_resource.ipython_path}") + Chef::Log.info("IPython settings are at #{new_resource.ipython_settings_dir}") + create_profile(new_resource.ipython_path, new_resource.owner, + new_resource.name, new_resource.ipython_settings_dir) end -def create_profile(ipython_path, owner, name, ipython_settings_dir) - bash "create_profile" do - user owner - group owner - code <<-EOH - #{ipython_path} profile create --profile=#{name} --ipython-dir #{ipython_settings_dir} - EOH - environment - end +# TO DO - FIX JUPYTER CONFIG! +def create_profile(ipython_path, owner, _name, _ipython_settings_dir) + bash 'create_profile' do + user owner + group owner + code <<-EOH + # #{ipython_path} notebook --generate-config + EOH + environment + end end - diff --git a/recipes/default.rb b/recipes/default.rb index 4591f5b..6fad868 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -6,88 +6,97 @@ # Licensed under the Apache 2.0 License. # -include_recipe "python" +# include build-essential +include_recipe 'build-essential::default' # Unless the paths got overridden, we set them up here -if node[:ipynb][:home_dir].nil? || node[:ipynb][:home_dir].empty? - node.set[:ipynb][:home_dir] = File.join("/home/", node[:ipynb][:linux_user]) +if node['ipynb']['home_dir'].nil? || node['ipynb']['home_dir'].empty? + node.default['ipynb']['home_dir'] = File.join('/home/', node['ipynb']['linux_user']) end -if node[:ipynb][:notebook_dir].nil? || node[:ipynb][:notebook_dir].empty? - node.set[:ipynb][:notebook_dir] = File.join(node[:ipynb][:home_dir], - "notebooks") +if node['ipynb']['notebook_dir'].nil? || node['ipynb']['notebook_dir'].empty? + node.default['ipynb']['notebook_dir'] = File.join(node['ipynb']['home_dir'], + 'notebooks') end -if node[:ipynb][:virtenv].nil? || node[:ipynb][:virtenv].empty? - node.set[:ipynb][:virtenv] = File.join(node[:ipynb][:home_dir], ".ipyvirt") +if node['ipynb']['virtenv'].nil? || node['ipynb']['virtenv'].empty? + node.default['ipynb']['virtenv'] = File.join(node['ipynb']['home_dir'], '.ipyvirt') end # Make the package manager handle an initial install so that we # have system dependencies, whether we run IPython from site-packages or a # virtualenv. -node[:ipynb][:system_packages].each do |pkg| - package pkg do - action :install - end +node['ipynb']['system_packages'].each do |pkg| + package pkg do + action :install + end end # Group running the IPython notebook (*nix permissions) -group node[:ipynb][:linux_group] do - group_name node[:ipynb][:linux_group] - action :create +group node['ipynb']['linux_group'] do + group_name node['ipynb']['linux_group'] + action :create end # User (also runs the IPython notebook) -user node[:ipynb][:linux_user] do +user node['ipynb']['linux_user'] do comment 'User for ipython notebook' - gid node[:ipynb][:linux_group] - home node[:ipynb][:home_dir] + gid node['ipynb']['linux_group'] + home node['ipynb']['home_dir'] shell '/bin/bash' - supports :manage_home => true + manage_home true action :create end +# Ensure the requested python version is available +python_runtime 'notebook_interpreter' do + version node['ipynb']['py_version'] +end + # Create a virtual environment -python_virtualenv node[:ipynb][:virtenv] do - interpreter node[:ipynb][:py_version] - owner node[:ipynb][:linux_user] - group node[:ipynb][:linux_group] - action :create +python_virtualenv node['ipynb']['virtenv'] do + python 'notebook_interpreter' + user node['ipynb']['linux_user'] + group node['ipynb']['linux_group'] + action :create + system_site_packages true end # Make sure uwsgi gets installed -python_pip "uwsgi" do - virtualenv node[:ipynb][:virtenv] - user node[:ipynb][:linux_user] - group node[:ipynb][:linux_group] - action :install -end +# python_package 'uwsgi' do +# virtualenv node['ipynb']['virtenv'] +# user node['ipynb']['linux_user'] +# group node['ipynb']['linux_group'] +# action :install +# end # Install the entire scientific computing stack -node[:ipynb][:scientific_stack].each do |pkg| - python_pip pkg do - virtualenv node[:ipynb][:virtenv] - user node[:ipynb][:linux_user] - group node[:ipynb][:linux_group] - action :install - end +node[:ipynb][:scientific_stack].each do |pkg, version| + python_package pkg do + version version unless version.nil? + virtualenv node['ipynb']['virtenv'] + user node['ipynb']['linux_user'] + group node['ipynb']['linux_group'] + action :install + end end # IPython proper -python_pip node[:ipynb][:ipython_package] do - virtualenv node[:ipynb][:virtenv] - user node[:ipynb][:linux_user] - group node[:ipynb][:linux_group] - action :install +python_package node['ipynb']['ipython_package'] do + version node['ipynb']['ipython_package_version'] unless node['ipynb']['ipython_package_version'].nil? + virtualenv node['ipynb']['virtenv'] + user node['ipynb']['linux_user'] + group node['ipynb']['linux_group'] + action :install end # Any additional packages to build into the same virtual environment -node[:ipynb][:extra_packages].each do |pkg| - python_pip pkg do - virtualenv node[:ipynb][:virtenv] - user node[:ipynb][:linux_user] - group node[:ipynb][:linux_group] - action :install - end +node[:ipynb][:extra_packages].each do |pkg, version| + python_package pkg do + version version unless version.nil? + virtualenv node['ipynb']['virtenv'] + user node['ipynb']['linux_user'] + group node['ipynb']['linux_group'] + action :install + end end - diff --git a/recipes/proxy.rb b/recipes/proxy.rb index 1cbee7c..b2c8e3a 100644 --- a/recipes/proxy.rb +++ b/recipes/proxy.rb @@ -1,16 +1,16 @@ def cert_up(cert_file, cert_file_text) - # If certificate file is passed as an attribute - unless node[:ipynb][cert_file_text].nil? - # Set a default spot for the certificate file - file node[:ipynb][cert_file] do - owner 'root' - group 'root' - mode '0600' - action :create - content node[:ipynb][cert_file_text] - end - end + # If certificate file is passed as an attribute + # Set a default spot for the certificate file + file cert_file do + owner 'root' + group 'root' + mode '0600' + action :create + content cert_file_text + sensitive true + not_if { cert_file_text.nil? } + end end ########################################################################### @@ -19,44 +19,23 @@ def cert_up(cert_file, cert_file_text) # nginx version must be greater than 1.4.x in order to support # web sockets (for interacting with the IPython kernel) # -# Chef-solo is behaving oddly for setting these attributes in -# attributes/default.rb, so I inject here -# ########################################################################### -node.set[:nginx][:default_site_enabled] = false - -node.set[:nginx][:version] = "1.5.3" -node.set[:nginx][:source][:version] = "1.5.3" -# The Chef checksum of a binary is determined by: shasum -a 256 FILE_NAME -node.set[:nginx][:source][:checksum] = "edcdf2030750b4eb1ba8cd79365c16a3e33e6136b7fdd8a1a7b4082397f4e92b" -node.set[:nginx][:source][:prefix] = "/opt/nginx-#{node[:nginx][:source][:version]}" -node.set[:nginx][:source][:url] = "http://nginx.org/download/nginx-#{node[:nginx][:source][:version]}.tar.gz" -node.set[:nginx][:source][:sbin_path] = "#{node[:nginx][:source][:prefix]}/sbin/nginx" - -node.set[:nginx][:source][:default_configure_flags] = [ - "--prefix=#{node[:nginx][:source][:prefix]}", - "--conf-path=#{node[:nginx][:dir]}/nginx.conf", - "--sbin-path=#{node[:nginx][:source][:sbin_path]}" -] -node.set[:nginx][:init_style] = "runit" - -include_recipe "nginx::source" +include_recipe 'nginx::source' # Install certs -cert_up(:ssl_certificate, :ssl_certificate_text) -cert_up(:ssl_certificate_key, :ssl_certificate_key_text) +cert_up(node['ipynb']['ssl_certificate'], node['ipynb']['ssl_certificate_text']) +cert_up(node['ipynb']['ssl_certificate_key'], node['ipynb']['ssl_certificate_key_text']) -template "/etc/nginx/sites-available/#{node[:ipynb][:proxy][:hostname]}" do - source "nginx-proxy.erb" - notifies :restart, "service[nginx]" +template "/etc/nginx/sites-available/#{node['ipynb']['proxy']['hostname']}" do + source 'nginx-proxy.erb' + notifies :restart, 'service[nginx]' end -nginx_site "default" do - enable false +nginx_site 'default' do + enable false end -nginx_site node[:ipynb][:proxy][:hostname] do - enable true +nginx_site node['ipynb']['proxy']['hostname'] do + enable true end - diff --git a/recipes/virtenv_launch.rb b/recipes/virtenv_launch.rb index 818fb8e..3610254 100644 --- a/recipes/virtenv_launch.rb +++ b/recipes/virtenv_launch.rb @@ -20,81 +20,59 @@ # Create a full IPython installation along with standard scientific computing tools -include_recipe "supervisor" - -ipython_settings_dir = File.join(node[:ipynb][:home_dir], ".ipython") +ipython_settings_dir = File.join(node['ipynb']['home_dir'], '.jupyter') # Create the directory for storing notebooks -directory node[:ipynb][:notebook_dir] do - owner node[:ipynb][:linux_user] - group node[:ipynb][:linux_group] - mode '0775' - action :create +directory node['ipynb']['notebook_dir'] do + owner node['ipynb']['linux_user'] + group node['ipynb']['linux_group'] + mode '0775' + action :create end # Make sure the default profile exists, to deal with IPython bugs/strangeness -ipynb_profile 'default' do - action :create - owner node[:ipynb][:linux_user] - ipython_path "#{node[:ipynb][:virtenv]}/bin/ipython" - ipython_settings_dir ipython_settings_dir -end +# ipynb_profile 'default' do +# action :create +# owner node['ipynb']['linux_user'] +# ipython_path "#{node['ipynb']['virtenv']}/bin/jupyter" +# ipython_settings_dir ipython_settings_dir +# end + +# ipynb_profile node['ipynb']['profile_name'] do +# action :create +# owner node['ipynb']['linux_user'] +# ipython_path "#{node['ipynb']['virtenv']}/bin/jupyter" +# ipython_settings_dir ipython_settings_dir +# end + +nb_config = File.join(ipython_settings_dir, 'jupyter_notebook_config.py') -ipynb_profile node[:ipynb][:profile_name] do - action :create - owner node[:ipynb][:linux_user] - ipython_path "#{node[:ipynb][:virtenv]}/bin/ipython" - ipython_settings_dir ipython_settings_dir +# Set the password hash if the password is set +unless node['ipynb']['NotebookApp']['password'].nil? + ipy_hash = IPythonAuth.ipython_hash(node['ipynb']['NotebookApp']['password']) + node.set['ipynb']['NotebookApp']['password_hash'] = ipy_hash end -ipynb_mathjax "MathJax!" do - action :create - owner node[:ipynb][:linux_user] - ipython_path "#{node[:ipynb][:virtenv]}/bin/ipython" - install_dir File.join(node[:ipynb][:virtenv], "lib", node[:ipynb][:py_version], - "site-packages/IPython/html/static/mathjax") +directory "/home/#{node['ipynb']['linux_user']}/.jupyter" do + owner node['ipynb']['linux_user'] + group node['ipynb']['linux_group'] end -profile_dir = File.join(ipython_settings_dir, - "profile_" + node[:ipynb][:profile_name]) - -nb_config = File.join(profile_dir, "ipython_notebook_config.py") - - -# Set the password hash if the password is set -unless node[:ipynb][:NotebookApp][:password].nil? - ipy_hash = IPythonAuth.ipython_hash(node[:ipynb][:NotebookApp][:password]) - node.set[:ipynb][:NotebookApp][:password_hash] = ipy_hash -end - -# Write over the profile with our own built template +# Write over the configuration with our own built template template nb_config do - owner node[:ipynb][:linux_user] - group node[:ipynb][:linux_group] - mode 00644 - source "ipython_notebook_config.py.erb" + owner node['ipynb']['linux_user'] + group node['ipynb']['linux_group'] + mode 00644 + source 'jupyter_notebook_config.py.erb' end -# Setup an IPython notebook service -supervisor_service node[:ipynb][:service_name] do - user node[:ipynb][:linux_user] - directory node[:ipynb][:home_dir] - - # IPython notebook should have access to the shell - environment "HOME" => node[:ipynb][:home_dir], - "SHELL" => "/bin/bash", - "USER" => node[:ipynb][:linux_user], - "PATH" => "#{node[:ipynb][:virtenv]}/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games", - "VIRTUAL_ENV" => "#{node[:ipynb][:virtenv]}" - - # Make the path for the service be the virtualenvironment - #environment "PATH" => (File.join(node[:ipynb][:virtenv], "bin") + ":$PATH") - action :enable - autostart true - autorestart true - - # Start up the IPython notebook as a service - command "#{node[:ipynb][:virtenv]}/bin/ipython notebook --profile=#{node[:ipynb][:profile_name]}" - stopsignal "QUIT" +poise_service node['ipynb']['service_name'] do + user node['ipynb']['linux_user'] + command "#{node['ipynb']['virtenv']}/bin/jupyter notebook" + directory node['ipynb']['home_dir'] + environment 'HOME' => node['ipynb']['home_dir'], + 'SHELL' => '/bin/bash', + 'USER' => node['ipynb']['linux_user'], + 'PATH' => "#{node['ipynb']['virtenv']}/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games", + 'VIRTUAL_ENV' => node['ipynb']['virtenv'] end - diff --git a/resources/mathjax.rb b/resources/mathjax.rb deleted file mode 100644 index 6cd2f37..0000000 --- a/resources/mathjax.rb +++ /dev/null @@ -1,33 +0,0 @@ -# -# Author:: Kyle Kelley -# Cookbook Name:: ipynb -# Resource:: mathjax -# -# Copyright:: 2013, Rackspace -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -actions :create #, :delete, :create_if_missing -default_action :create if defined?(default_action) - -# Default action for Chef <= 10.8 -def initialize(*args) - super - @action = :create -end - -attribute :install_dir -attribute :owner, :regex => Chef::Config[:user_valid_regex], :default => node[:ipynb][:linux_user] -attribute :ipython_path, :kind_of => String, :default => "#{node[:ipynb][:virtenv]}/bin/ipython" - diff --git a/resources/profile.rb b/resources/profile.rb index f1010f4..21a9217 100644 --- a/resources/profile.rb +++ b/resources/profile.rb @@ -18,16 +18,15 @@ # limitations under the License. # -actions :create #, :delete, :create_if_missing +actions :create # , :delete, :create_if_missing default_action :create if defined?(default_action) # Default action for Chef <= 10.8 def initialize(*args) - super - @action = :create + super + @action = :create end -attribute :owner, :regex => [ /^([a-z]|[A-Z]|[0-9]|_|-)+$/, /^\d+$/ ], :default => node[:ipynb][:linux_user] -attribute :ipython_path, :kind_of => String, :default => "#{node[:ipynb][:virtenv]}/bin/ipython" -attribute :ipython_settings_dir, :kind_of => String - +attribute :owner, regex: [/^([a-z]|[A-Z]|[0-9]|_|-)+$/, /^\d+$/], default: node['ipynb']['linux_user'] +attribute :ipython_path, kind_of: String, default: "#{node['ipynb']['virtenv']}/bin/ipython" +attribute :ipython_settings_dir, kind_of: String diff --git a/templates/default/ipython_notebook_config.py.erb b/templates/default/jupyter_notebook_config.py.erb similarity index 73% rename from templates/default/ipython_notebook_config.py.erb rename to templates/default/jupyter_notebook_config.py.erb index e307628..48a2441 100644 --- a/templates/default/ipython_notebook_config.py.erb +++ b/templates/default/jupyter_notebook_config.py.erb @@ -13,17 +13,9 @@ c = get_config() # Kernel config -<% unless node['ipynb']['NotebookApp']['pylab'].nil? %> - -# Pre-load matplotlib and numpy for interactive use, selecting a particular -# matplotlib backend and loop integration. -# Choices: ['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'] -c.IPKernelApp.pylab = '<%= node['ipynb']['NotebookApp']['pylab'] %>' -<% end %> - <% unless node['ipynb']['notebook_dir'].nil? %> # Set notebook home directory -c.FileNotebookManager.notebook_dir = u'<%= node['ipynb']['notebook_dir'] %>' +c.NotebookApp.notebook_dir = u'<%= node['ipynb']['notebook_dir'] %>' <% end %> <% unless node['ipynb']['proxy']['enable'] %> @@ -52,12 +44,12 @@ c.NotebookApp.open_browser = <%= node['ipynb']['NotebookApp']['open_browser'] %> <% unless node['ipynb']['NotebookApp']['password_hash'].nil? %> # -# Password created using IPython.lib.passwd +# Password created using notebook.lib.passwd # # Example: # -# In [1]: from IPython.lib import passwd -# In [2]: passwd() +# In [1]: from notebook.auth import passwd; +# In [2]: passwd() # Enter password: # Verify password: # Out[2]: 'sha1:d2fb9930b3ed:8facdbc05c08e1affbc8424a0717c2b21d10f4a3' @@ -65,12 +57,18 @@ c.NotebookApp.open_browser = <%= node['ipynb']['NotebookApp']['open_browser'] %> c.NotebookApp.password = '<%= node['ipynb']['NotebookApp']['password_hash'] %>' <% end %> -c.NotebookApp.webapp_settings = {'static_url_prefix':'/static/'} +# Initial login token, used if pasword is not set +<% if node['ipynb']['NotebookApp']['password_hash'].nil? %> +c.NotebookApp.token = '<%= node['ipynb']['NotebookApp']['token'] %>' +<% end %> + + +c.NotebookApp.tornado_settings = {'static_url_prefix':'/static/'} # # Adding whatever content you feel like to the notebook config file. You # have to make sure it does not interfere with parameters already covered -# in ipython_notebook_config.py ruby template. +# in jupyter_notebook_config.py ruby template. # <%= node['ipynb']['NotebookApp']['additional_config'] %> diff --git a/test/integration/default/jupyter_service.rb b/test/integration/default/jupyter_service.rb new file mode 100644 index 0000000..4bf956e --- /dev/null +++ b/test/integration/default/jupyter_service.rb @@ -0,0 +1,16 @@ +# ensure configuration file exists +file '/home/vagrant/.jupyter/jupyter_notebook_config.py' do + it { should exist } +end + +# ensure our service is running +describe service 'jupyter' do + it { should be_running } +end + +# verify service is listening +describe port(8888) do + its('addresses') { should include '127.0.0.1' } + its('protocols') { should eq ['tcp'] } + it { should be_listening } +end From 0e7d387ffd07f8ac9012385809cead530023fd7d Mon Sep 17 00:00:00 2001 From: "David F. Severski" Date: Tue, 3 Jan 2017 07:47:55 -0800 Subject: [PATCH 11/11] Update README --- README.md | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index cece062..725a1f7 100644 --- a/README.md +++ b/README.md @@ -2,35 +2,31 @@ Sets up an IPython Notebook server using Chef. -This cookbook targets IPython 1.0.0 and will not deploy 0.x releases. +This cookbook targets Jupyter/IPython 4.x environment. -# Requirements - -This cookbook uses Chef 11. Additionally, Berkshelf is recommended but not required. +CAUTION: This cookbook now (Jan, 2017) defaults to using Jupyter and IPython versus the old +monolithic IPython stack. While testing has been performed, if you are dependent on the +old behavior, you should use the V1.1.1 tagged release of this cookbook. -## Requirements for Vagrant +# Requirements - * [Berkshelf][]: `gem install berks` - * [Vagrant][] 1.2.4 or higher - * Berkshelf plugin for Vagrant: `vagrant plugin install vagrant-berkshelf` - * Omnibus plugin for Vagrant: `vagrant plugin install vagrant-omnibus` +This cookbook uses Chef 12.1+. # Usage ## Include this cookbook -This cookbook isn't on opscode (yet), so for now you'll have to use Berkshelf and point to it in your Berksfile +This cookbook isn't on supermarket (yet), so for now you'll have to use Berkshelf and point to it in your Berksfile ```ruby -cookbook 'ipynb', - :git => 'https://github.com/rgbkrk/ipynb-cookbook' +cookbook 'ipynb', github: 'rgbkrk/ipynb-cookbook' ``` ## Bootstrap VirtualBox -You can also try it out using Vagrant with VirtualBox. +You can also try it out using test-kitchen. - vagrant up + test-kitchen converge ubuntu-16 Once finished, the IPython notebook can be accessed from your host machine (through port forwarding) on 127.0.0.1:9999. @@ -67,6 +63,16 @@ On a real deployment, these should be set using an encrypted data bag. 4. Push to the branch (`git push origin feature1`) 5. Create a new Pull Request +# Future Directions + +This cookbook satisfies the needs of the current collaborators. To do items include: +- Supporting non-Ubuntu platforms (Amazon, Centos, etc.) +- Support for non-IPython kernels (Rstats) +- Submission to Supermarket +- CI testing + +Contributions are most welcome! + # Author Author:: Kyle Kelley (kyle.kelley@rackspace.com)