diff --git a/.gitignore b/.gitignore index 28e7314..2b3e7a5 100644 --- a/.gitignore +++ b/.gitignore @@ -18,8 +18,8 @@ bin/* .kitchen/ .kitchen.local.yml -# anaconda installs should not be checked in -Anaconda-*-Linux-*.sh +# local anaconda installers should not be checked in +Anaconda*-*-Linux-*.sh # OSX .DS_Store diff --git a/.kitchen.yml b/.kitchen.yml index 68e4bbf..fb4964d 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -1,6 +1,12 @@ --- driver: - name: vagrant + # you can restore this if you want, but it'll be slooooooow + #name: vagrant + name: docker +driver_config: + binary: /usr/local/bin/docker + # install latest if not present + require_chef_omnibus: true provisioner: # it would be nice if this supported multiple provisioners (ordered) like vagrant does... @@ -8,15 +14,21 @@ provisioner: name: chef_solo platforms: + # ubuntu: 2 LTS, and the latest - name: ubuntu-12.04 -# - name: ubuntu-12.10 -# driver: -# box: chef/ubuntu-11.10 -# - name: ubuntu-13.04 -# driver: -# box: chef/ubuntu-13.04 - - name: ubuntu-13.10 - name: ubuntu-14.04 + - name: ubuntu-15.04 + # debian: stable, oldstable + # TODO 7.9 and 8.2 were recently released + - name: debian-7.8 + - name: debian-8.1 + # centos + - name: centos-5.11 + # TODO 6.7 is the latest + - name: centos-6.6 + - name: centos-7.1.1503 + # redhat: 5.9, 6.6, 7.1 + # TODO what's the platform name in docker? suites: - name: default diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..16f9cdb --- /dev/null +++ b/.rspec @@ -0,0 +1,2 @@ +--color +--format documentation diff --git a/.ruby-gemset b/.ruby-gemset deleted file mode 100644 index 88be633..0000000 --- a/.ruby-gemset +++ /dev/null @@ -1 +0,0 @@ -chef-anaconda diff --git a/.ruby-version b/.ruby-version deleted file mode 100644 index eca07e4..0000000 --- a/.ruby-version +++ /dev/null @@ -1 +0,0 @@ -2.1.2 diff --git a/Berksfile b/Berksfile index 26c74c6..967b9a7 100644 --- a/Berksfile +++ b/Berksfile @@ -1,3 +1,3 @@ -source "http://api.berkshelf.com" +source "https://supermarket.chef.io" metadata diff --git a/CHANGELOG.md b/CHANGELOG.md index 297cbe5..8eed1d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,49 @@ # CHANGELOG +## 0.6.0 + +**This is a backwards-INCOMPATIBLE release** + +API, cookbook changes: + +- Refactored attributes to be cleaner and more readable +- The user and group are now created if they don't exist, and by default are + installed under anaconda/anaconda +- New attributes for configuring notebook server +- The OS architecture (x86 versus x86_64) is now autodetected by default + +Platform, support changes: + +- Added support for Anaconda 2.3 (all pythons and all architectures) +- Removed support for all Anacondas < 2.2.0 +- updated metadata.rb 'supports' tags (hopefully this doesn't break anything) + +Tools changes: + +- Migrated to chefdk 0.8.1 + - upgraded gems + - updated chefspec + - updated documentation + - removed rbenv/rvm files + +Testing changes: + +- Moved to kitchen-docker for Docker-based testing, which is much much much + faster +- Updated supported (tested) platforms: + - ubuntu: + - removed: 12.10, 13.04, 13.10 + - added: 15.04 + - debian: + - removed: 6.0.5 + - added: 7.8, 8.1 (7.9 and 8.2 not in fauxhai yet) + - centos: + - removed: 5.8, 6.0, 6.3 + - added: 5.11, 6.6, 7.1.1503 + - redhat (chefspec only, no kitchen testing): + - removed: 5.8, 6.3 + - added: 5.9, 6.6, 7.1.1503 + ## 0.5.1 - Added support for Anaconda 2.2.0 with Python 3 diff --git a/Gemfile b/Gemfile index 6ffba7d..34bf0b0 100644 --- a/Gemfile +++ b/Gemfile @@ -3,7 +3,10 @@ source 'https://rubygems.org' gem 'berkshelf' gem 'chefspec' -gem 'kitchen-vagrant' +gem 'test-kitchen' +# removed in favor of kitchen-docker +#gem 'kitchen-vagrant' +gem 'kitchen-docker' gem 'foodcritic' diff --git a/README.md b/README.md index e294392..52d08d5 100644 --- a/README.md +++ b/README.md @@ -3,68 +3,84 @@ Chef cookbook for installing [Continuum Analytic](http://continuum.io/)'s [Anaconda](https://store.continuum.io/cshop/anaconda/): "completely free Python distribution for large-scale data processing, predictive analytics, and -scientific computing". +scientific computing". Specifically: + +- Anaconda 2.2 or 2.3 + - python2 or python3 + - x86 or x86_64 +- Miniconda + - python2 or python3 + - x86 or x86_64 +- Usage tested on Ubuntu, unittested on Debian, CentOS, and RedHat. See [rspec + tests](spec/default_spec.rb#L100) and [kitchen tests](.kitchen.yml#L16) for + the full list. + +This also serves as an example for developing and testing Chef cookbooks. It +uses: + +- [ChefDK](https://downloads.chef.io/chef-dk/); 0.8.1 + - chef-client 12.4.4 + - [Berkshelf](http://berkshelf.com) for dependency resolution; 3.3.0 + - [Test Kitchen](https://github.com/test-kitchen/test-kitchen) for + comprehensive testing across multiple platforms, with tests written in + [serverspec](http://serverspec.org); 1.4.2 + - Docker, with + [kitchen-docker](https://github.com/portertech/kitchen-docker) + integration + - [Foodcritic](http://acrmp.github.io/foodcritic/) for style checking; 5.0.0 +- RSpec/[Chefspec](https://github.com/sethvargo/chefspec) for rapid testing; + 3.3.2 + +In addition: + +- [Vagrant](https://www.vagrantup.com) to provide an out-of-the-box working + example; 1.7.4 -This also serves as a live example of the most up-to-date best practices for -writing, maintaining, and testing Chef cookbooks: +## Requirements -- [Berkshelf 3](http://berkshelf.com/) for dependency resolution -- [Vagrant](https://www.vagrantup.com) for development -- [Chefspec](https://github.com/sethvargo/chefspec) for rapid testing -- [Test Kitchen](https://github.com/test-kitchen/test-kitchen) for -comprehensive testing across multiple platforms, with tests written in -[serverspec](http://serverspec.org/) -- [Foodcritic](http://acrmp.github.io/foodcritic/) for style checking +If you want to just have a working Anaconda VM, install: -## Requirements +- Vagrant -This repo has only been tested with RVM; YMMV with other installation methods -(rbenv, chef-dk, etc). +For the full experience (e.g. running the test suite), also install: -- Berkshelf 3.1.3 -- Chefspec 4.0.0 -- Test Kitchen 1.2.1 -- Foodcritic 4.0.0 -- Vagrant 1.6+ +- ChefDK - [vagrant-omnibus](https://github.com/schisamo/vagrant-omnibus) - - [vagrant-berkshelf](https://github.com/berkshelf/vagrant-berkshelf): note - that `>= 2.0.1` is required - -It sounds like [Chef-DK](http://www.getchef.com/downloads/chef-dk/) is the new -recommended installation path, but I have not had a good experience with it (as -of *0.1.0-1*). Again, YMMV. + - [vagrant-berkshelf](https://github.com/berkshelf/vagrant-berkshelf) +- Docker + - Don't forget [Docker Machine](https://docs.docker.com/machine/) if you're + on OSX; installing this via homebrew is highly recommended. ## Quickstart -The [Vagrantfile](Vagrantfile) is written to get you an Anaconda environment -with minimal effort (though it will take at least a few minutes to download the -Anaconda installer itself): - -```bash -$> vagrant up --provision -... +The sample [Vagrantfile](Vagrantfile) will build you an Anaconda VM with no +changes necessary; note it might take a few minutes to download the Anaconda +installer itself. -$> vagrant ssh -$vagrant> export PATH=/opt/anaconda/2.2.0/bin:${PATH} -$vagrant> conda --version -conda 3.10.0 + ```bash + $> vagrant up --provision + ... -# if you included `recipe[anaconda::shell_conveniences]` you don't have to do anything; -# it's sourced in /etc/profile.d -$> vagrant ssh -$vagrant> conda --version -conda 3.10.0 -``` + # the sample image includes `recipe[anaconda::shell_conveniences]`, which + # means conda is already in PATH via /etc/profile.d + $> vagrant ssh + $vagrant> conda --version + conda 3.14.1 -In addition, by default an IPython notebook server is enabled and started: + # or you add it to PATH manually + $> vagrant ssh + $vagrant> export PATH=/opt/anaconda/2.3.0/bin:${PATH} + $vagrant> conda --version + conda 3.14.1 + ``` - http://33.33.33.123:8888 +It includes a Jupyter (IPython) notebook server accessible at -To use it in a cookbook: +Lastly, to use it in a cookbook: -```ruby -include_recipe 'anaconda::default' -``` + ```ruby + include_recipe 'anaconda::default' + ``` ## Warning! If you're also using the [python](https://github.com/poise/python) cookbook... @@ -79,49 +95,47 @@ The main recipe is `anaconda::default`. Include it in your runlist, and it will install the package as well as any necessary dependencies. The following are user-configurable attributes. Check -[attributes/default.rb](attributes/default.rb) for default values. +[attributes/default.rb](attributes/default.rb) for more details. - `anaconda` - - `version`: the version to install. Valid values are: - - 1.8.0 - - 1.9.2 - - 2.0.1 - - 2.1.0 + - `version`: the Anaconda version to install. Valid values are: - 2.2.0 - - 3-2.2.0 (uses Python 3.4) - - miniconda-python2 - - miniconda-python3 - - `flavor`: either `x86` (32-bit) or `x86_64` (64-bit) + - 2.3.0 + - latest (for miniconda only) + - `python`: which version of Python to install for. Valid values are: + - python2 + - python3 + - `flavor`: what architecture the instance is. Valid values are: + - nil (will autodetect) + - x86 (32-bit) + - x86_64 (64-bit) + - `install_type`: which Anaconda distribution to install. Valid values are: + - anaconda + - miniconda - `install_root`: the parent directory of all anaconda installs. note that individual installs go into `#{install_root}/#{version}` - - `accept_license`: must be explicitly set to the string `yes`; any other - value will reject the license. + - `accept_license`: **must be explicitly set to the string `yes` (there are + no defaults)**; any other value will reject the license. - `owner`: the user who owns the install - `group`: the group who owns the install ### `recipe[anaconda::shell_conveniences]` Include this to have the environment set for all users (login shells) via -`/etc/profile.d`. Useful for development. - -```bash -$> vagrant ssh -$vagrant> which conda -/opt/anaconda/2.0.1/bin/conda -``` +`/etc/profile.d`. Useful for development. ### resource `anaconda_package` You can use the `anaconda_package` resource to install new packages into the Anaconda environment: -```ruby -# I do not know what 'astroid' is, just using it as a sample package -anaconda_package 'astroid' do - # the other supported action is `:remove` - action :install -end -``` + ```ruby + # I don't know what 'astroid' is, just using it as a sample package + anaconda_package 'astroid' do + # the other supported action is `:remove` + action :install + end + ``` See the [resource definition](resources/package.rb) for additional options; in general, all it does is present the same options as `conda install`/`conda @@ -129,85 +143,82 @@ remove`. ### resource `anaconda_nbservice` -**This only works with a full Anaconda installation! I.e. the notebook service will not work out-of-the-box if installed with miniconda** - -The `anaconda_nbservice` will run an IPython notebook server as a runit -service: +**This only works with a full Anaconda installation! I.e. the notebook service +will not work out-of-the-box if installed with miniconda.** -```ruby -anaconda_nbservice 'notebook-server' do - # listen on all interfaces; there will be a warning since security is - # disabled - ip '*' - port '8888' +The `anaconda_nbservice` will run a Jupyter notebook server as a runit service: - user 'vagrant' - group 'vagrant' + ```ruby + anaconda_nbservice 'notebook-server' do + # listen on all interfaces; there will be a warning since security is + # disabled + ip '*' + port '8888' - install_dir '/opt/ipython/server' + install_dir '/opt/ipython/server' - service_action [ :enable, :start ] -end -``` + service_action [ :enable, :start ] + end + ``` The standard configuration should be good enough, but you might need to write your own run service template: -```ruby -anaconda_nbservice 'server-with-custom-template' do - user ipython_user - group ipython_group + ```ruby + anaconda_nbservice 'server-with-custom-template' do + user ipython_user + group ipython_group - install_dir install_dir + install_dir install_dir - template_cookbook 'your_cookbook' - # note that if your template name is TEMPLATE, then this value should be - # 'TEMPLATE", but the file should be 'sv-TEMPLATE-run.erb' - run_template_name 'your_template_name' - run_template_opts({ - ... - }) + template_cookbook 'your_cookbook' + # note that if your template name is TEMPLATE, then this value should be + # 'TEMPLATE", but the file should be 'sv-TEMPLATE-run.erb' + run_template_name 'your_template_name' + run_template_opts({ + ... + }) - service_action [ :enable, :start ] -end -``` + service_action [ :enable, :start ] + end + ``` ## Tests -Run the full test suite: +To run the full test suite: -```bash -# this will take a really long time -$> script/cibuild -... + ```bash + # this will take a while, especially the first time + $> script/cibuild + ... -# check the final result; bash return codes: 0 is good, anything else is not -$> echo $? -``` + # check the final result; bash return codes: 0 is good, anything else is not + $> echo $? + ``` -Run just the [chefspecs](spec/default_spec.rb): +- to run just the [chefspecs](spec/default_spec.rb): -```bash -$> rspec -``` + ```bash + $> rspec + ``` -Run just the test kitchen serverspec [integration -tests](test/integration/default/serverspec/default_spec.rb): +- to run just the test kitchen serverspec [integration + tests](test/integration/default/serverspec/default_spec.rb): -```bash -# this is what takes so long: every platform and version is fully built in vagrant -# the list of OSes is defined in [.kitchen.yml](.kitchen.yml) -$> kitchen verify + ```bash + # this is done via docker/kitchen-docker + # the list of OSes is defined in .kitchen.yml + $> kitchen verify -# test a specific OS; `kitchen list` -$> kitchen verify default-ubuntu-1204 -``` + # test a specific OS; `kitchen list` + $> kitchen verify default-ubuntu-1204 + ``` -Check the style with [Foodcritic](http://acrmp.github.io/foodcritic/): +- check for style issues with Foodcritic -```bash -$> foodcritic -``` + ```bash + $> foodcritic + ``` ## Releases and issues @@ -217,19 +228,18 @@ Standard stuff: - releases are [made with Github](https://github.com/thmttch/chef-continuum-anaconda/releases), and `git tag`'ed - -Issues should be [opened in the Github issue -tracker](https://github.com/thmttch/chef-continuum-anaconda/issues) +- issues should be [opened in the Github issue + tracker](https://github.com/thmttch/chef-continuum-anaconda/issues) ## TODO -- autodetect 64-bit versus 32 -- (TODO does it matter? who uses it?) populate metadata.rb: `suggests`, - `supports`, etc - add a pre-provision for kitchen tests to avoid redownloading the installer on every test (really slows down the tests) -- figure out how to publish onto http://community.opscode.com/; the - documentation is unbelievably bad +- https://github.com/poise/python is now deprecated, in favor of + https://github.com/poise/poise-python; see if the python workaround is still + necessary + - the supermarket version (https://supermarket.chef.io/cookbooks/python) + looks like it also points to the deprecated one ## Author diff --git a/Vagrantfile b/Vagrantfile index b90e89b..7eb7f49 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -1,6 +1,3 @@ -# -*- mode: ruby -*- -# vi: set ft=ruby : - Vagrant.configure('2') do |config| config.vm.hostname = 'anaconda-berkshelf' # 14.04 LTS @@ -29,18 +26,14 @@ Vagrant.configure('2') do |config| # dev optimization: anaconda's big, so put it in the cache for development if # it's already been downloaded [ - 'Anaconda-1.8.0-Linux-x86.sh', - 'Anaconda-1.8.0-Linux-x86_64.sh', - 'Anaconda-1.9.2-Linux-x86.sh', - 'Anaconda-1.9.2-Linux-x86_64.sh', - 'Anaconda-2.0.1-Linux-x86.sh', - 'Anaconda-2.0.1-Linux-x86_64.sh', - 'Anaconda-2.1.0-Linux-x86.sh', - 'Anaconda-2.1.0-Linux-x86_64.sh', 'Anaconda-2.2.0-Linux-x86.sh', 'Anaconda-2.2.0-Linux-x86_64.sh', 'Anaconda3-2.2.0-Linux-x86.sh', 'Anaconda3-2.2.0-Linux-x86_64.sh', + 'Anaconda-2.3.0-Linux-x86.sh', + 'Anaconda-2.3.0-Linux-x86_64.sh', + 'Anaconda3-2.3.0-Linux-x86.sh', + 'Anaconda3-2.3.0-Linux-x86_64.sh', ].each do |f| if File.exists?(f) config.vm.provision :shell do |shell| @@ -53,8 +46,6 @@ Vagrant.configure('2') do |config| config.vm.provision :chef_solo do |chef| chef.json = { :anaconda => { - :version => '3-2.2.0', - :flavor => 'x86_64', :accept_license => 'yes', } } @@ -69,3 +60,6 @@ Vagrant.configure('2') do |config| #chef.log_level = :debug end end + +# -*- mode: ruby -*- +# vi: set ft=ruby : diff --git a/attributes/default.rb b/attributes/default.rb index 015b911..66e321c 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -1,47 +1,53 @@ -default.anaconda.version = '2.2.0' -default.anaconda.flavor = 'x86' -default.anaconda.installer = { - '1.8.0' => { - 'uri_prefix' => 'http://09c8d0b2229f813c1b93-c95ac804525aac4b6dba79b00b39d1d3.r79.cf1.rackcdn.com', - 'x86' => '9eeda2307e9f5c7927ce610fc9dcd632c3d42fab', - 'x86_64' => '44da25d5fec8a1acc26bad816c928e002d877334', - }, - '1.9.2' => { - 'uri_prefix' => 'http://09c8d0b2229f813c1b93-c95ac804525aac4b6dba79b00b39d1d3.r79.cf1.rackcdn.com', - 'x86' => '806a8edec3cde7d3e883fe6fda6999b643766e06', - 'x86_64' => '8b3d2800b555c28879f51373ea8ca32c3c79a424', - }, - '2.0.1' => { - 'uri_prefix' => 'http://09c8d0b2229f813c1b93-c95ac804525aac4b6dba79b00b39d1d3.r79.cf1.rackcdn.com', - 'x86' => '7384b070191967f205e7856e9c82396867e22601', - 'x86_64' => 'd5b0e4e3619bd75fedcb0dafa585886198ec7014', - }, - '2.1.0' => { - 'uri_prefix' => 'http://09c8d0b2229f813c1b93-c95ac804525aac4b6dba79b00b39d1d3.r79.cf1.rackcdn.com', - 'x86' => 'fd70c08719e6b5caae45b7c8402c6975a8cbc0e3e2a9c4c977554d1784f28b72', - 'x86_64' => '191fbf290747614929d0bdd576e330c944b22a67585d1c185e0d2b3a3e65e1c0', - }, - '2.2.0' => { - 'uri_prefix' => 'https://3230d63b5fc54e62148e-c95ac804525aac4b6dba79b00b39d1d3.ssl.cf1.rackcdn.com', - 'x86' => '6437d5b08a19c3501f2f5dc3ae1ae16f91adf6bed0f067ef0806a9911b1bef15', - 'x86_64' => 'ca2582cb2188073b0f348ad42207211a2b85c10b244265b5b27bab04481b88a2', - }, - '3-2.2.0' => { - 'uri_prefix' => 'https://3230d63b5fc54e62148e-c95ac804525aac4b6dba79b00b39d1d3.ssl.cf1.rackcdn.com', - 'x86' => '223655cd256aa912dfc83ab24570e47bb3808bc3b0c6bd21b5db0fcf2750883e', - 'x86_64' => '4aac68743e7706adb93f042f970373a6e7e087dbf4b02ac467c94ca4ce33d2d1', +# for miniconda this must be 'latest' +default.anaconda.version = '2.3.0' +# the version of python: either 'python2' or 'python3' +default.anaconda.python = 'python2' +# the architecture: nil to autodetect, or either 'x86' or 'x86_64' +default.anaconda.flavor = nil +# either 'anaconda' or 'miniconda' +default.anaconda.install_type = 'anaconda' + +default.anaconda.installer_info = { + 'anaconda' => { + '2.2.0' => { + 'python2' => { + 'uri_prefix' => 'https://repo.continuum.io', + 'x86' => '6437d5b08a19c3501f2f5dc3ae1ae16f91adf6bed0f067ef0806a9911b1bef15', + 'x86_64' => 'ca2582cb2188073b0f348ad42207211a2b85c10b244265b5b27bab04481b88a2', + }, + 'python3' => { + 'uri_prefix' => 'https://repo.continuum.io', + 'x86' => '223655cd256aa912dfc83ab24570e47bb3808bc3b0c6bd21b5db0fcf2750883e', + 'x86_64' => '4aac68743e7706adb93f042f970373a6e7e087dbf4b02ac467c94ca4ce33d2d1', + }, + }, + '2.3.0' => { + 'python2' => { + 'uri_prefix' => 'https://3230d63b5fc54e62148e-c95ac804525aac4b6dba79b00b39d1d3.ssl.cf1.rackcdn.com', + 'x86' => '73fdbbb3e38207ed18e5059f71676d18d48fdccbc455a1272eb45a60376cd818', + 'x86_64' => '7c02499e9511c127d225992cfe1cd815e88fd46cd8a5b3cdf764f3fb4d8d4576', + }, + 'python3' => { + 'uri_prefix' => 'https://3230d63b5fc54e62148e-c95ac804525aac4b6dba79b00b39d1d3.ssl.cf1.rackcdn.com', + 'x86' => '4cc10d65c303191004ada2b6d75562c8ed84e42bf9871af06440dd956077b555', + 'x86_64' => '3be5410b2d9db45882c7de07c554cf4f1034becc274ec9074b23fd37a5c87a6f', + }, + }, }, - 'miniconda-python2' => { - 'uri_prefix' => 'https://repo.continuum.io/miniconda', - # miniconda is always latest, so it doesn't have a stable checksum - 'x86' => nil, - 'x86_64' => nil, + 'miniconda' => { + 'latest' => { + 'python2' => { + 'uri_prefix' => 'https://repo.continuum.io/miniconda', + 'x86' => nil, + 'x86_64' => nil, + }, + 'python3' => { + 'uri_prefix' => 'https://repo.continuum.io/miniconda', + 'x86' => nil, + 'x86_64' => nil, + }, + }, }, - 'miniconda-python3' => { - 'uri_prefix' => 'https://repo.continuum.io/miniconda', - 'x86' => nil, - 'x86_64' => nil, - } } # specific versions are installed _under_ this directory @@ -49,6 +55,16 @@ default.anaconda.accept_license = 'no' default.anaconda.package_logfile = nil -default.anaconda.owner = 'vagrant' -default.anaconda.group = 'vagrant' +default.anaconda.owner = 'anaconda' +default.anaconda.group = 'anaconda' default.anaconda.home = "/home/#{node.anaconda.owner}" + +default.anaconda.notebook = { + # by default, listens on all interfaces; there will be a warning since + # security is disabled + 'ip' => '*', + 'port' => 8888, + 'owner' => node.anaconda.owner, + 'group' => node.anaconda.group, + 'install_dir' => '/opt/ipython/server', +} diff --git a/metadata.rb b/metadata.rb index cd60820..0b263ae 100644 --- a/metadata.rb +++ b/metadata.rb @@ -4,12 +4,25 @@ license 'MIT' description 'Installs/Configures anaconda' long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) -version '0.5.2' +version '0.6.0' supports 'ubuntu', '= 12.04' -supports 'ubuntu', '= 13.04' -supports 'ubuntu', '= 13.10' supports 'ubuntu', '= 14.04' +supports 'ubuntu', '= 15.04' + +supports 'debian', '= 7.8' +supports 'debian', '= 8.1' + +supports 'centos', '= 5.11' +supports 'centos', '= 6.6' +supports 'centos', '= 7.1.1503' + +# TODO +#supports 'redhat', '= 5.9' +#supports 'redhat', '= 6.6' +#supports 'redhat', '= 7.1' depends 'apt' depends 'runit' +depends 'bzip2' +depends 'tar' diff --git a/providers/nbservice.rb b/providers/nbservice.rb index 563efec..d4a02ff 100644 --- a/providers/nbservice.rb +++ b/providers/nbservice.rb @@ -20,17 +20,23 @@ def log_opts(node) action :create do r = new_resource + # fill in any missing attributes with the defaults + ip = r.ip || node.anaconda.notebook.ip + port = r.port || node.anaconda.notebook.port + owner = r.owner || node.anaconda.notebook.owner + group = r.group || node.anaconda.notebook.group + install_dir = r.install_dir || node.anaconda.notebook.install_dir - directory r.install_dir do - owner r.user - group r.group + directory install_dir do + owner owner + group group recursive true end - ipython_dir = "#{r.install_dir}/.ipython" + ipython_dir = "#{install_dir}/.ipython" directory ipython_dir do - owner r.user - group r.group + owner owner + group group recursive true end @@ -39,15 +45,12 @@ def log_opts(node) files_to_source = r.files_to_source || [ ] service_action = r.service_action || [ :enable, :start ] - ip = r.ip || '*' - port = r.port || '8888' - template_cookbook = r.template_cookbook || 'anaconda' run_template_name = r.run_template_name || 'ipython-notebook' run_template_opts = r.run_template_opts || { - :user => r.user, + :owner => owner, :cmd_ipython => cmd_ipython(), - :notebook_dir => r.install_dir, + :notebook_dir => install_dir, :ipython_dir => ipython_dir, :ip => ip, :port => port, diff --git a/recipes/default.rb b/recipes/default.rb index 3dcf843..5b2adb7 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -8,27 +8,57 @@ # include_recipe 'apt::default' +# ubuntu: base docker images don't have bzip installed, which the anaconda +# installer needs +include_recipe 'bzip2::default' +# centos: base docker images don't have tar (?!?) +include_recipe 'tar::default' -version = node.anaconda.version -flavor = node.anaconda.flavor +# make sure the desired user and group exists +group node.anaconda.group +user node.anaconda.owner do + gid node.anaconda.group +end -anaconda_install_dir = "#{node.anaconda.install_root}/#{version}" +version = node.anaconda.version +python_version = node.anaconda.python +flavor = node.anaconda.flavor || ( + case node.kernel.machine + when 'i386', 'i686' + 'x86' + when 'x86_64' + 'x86_64' + else + Chef::Log.fatal!("Unrecognized node.kernel.machine=#{node.kernel.machine}; please explicitly node.anaconda.flavor", 1) + end +) +Chef::Log.debug "Autodetected node.kernel.machine=#{node.kernel.machine}, implying flavor=#{flavor}" +install_type = node.anaconda.install_type +installer_info = node.anaconda.installer_info[install_type][version][python_version] -installer = - if 'miniconda-python2' == version - "Miniconda-latest-Linux-#{flavor}.sh" - elsif 'miniconda-python3' == version - "Miniconda3-latest-Linux-#{flavor}.sh" - elsif '3-2.2.0' == version - "Anaconda3-2.2.0-Linux-#{flavor}.sh" +# e.g. +# Anaconda-2.3.0-Linux-x86 +# Anaconda3-2.3.0-Linux-x86 +# Miniconda-latest-Linux-x86 +# Miniconda3-latest-Linux-x86 +installer_basename = + if install_type == 'anaconda' + "Anaconda#{python_version == 'python3' ? '3' : ''}-#{version}-Linux-#{flavor}.sh" else - "Anaconda-#{version}-Linux-#{flavor}.sh" + Chef::Log.debug "miniconda installs ONLY have version = latest; setting it now" + node.anaconda.version = 'latest' + version = 'latest' + "Miniconda#{python_version == 'python3' ? '3' : ''}-#{version}-Linux-#{flavor}.sh" end -Chef::Log.debug "installer = #{installer}" +Chef::Log.debug "installer_basename = #{installer_basename}" -installer_path = "#{Chef::Config[:file_cache_path]}/#{installer}" -installer_source = "#{node.anaconda.installer[version]['uri_prefix']}/#{installer}" -installer_checksum = node.anaconda.installer[version][flavor] +# where the installer will install to +anaconda_install_dir = "#{node.anaconda.install_root}/#{version}" +# where the installer is downloaded to locally +installer_path = "#{Chef::Config[:file_cache_path]}/#{installer_basename}" +# where to download the installer from +installer_source = "#{installer_info['uri_prefix']}/#{installer_basename}" +installer_checksum = installer_info[flavor] installer_config = 'installer_config' installer_config_path = "#{Chef::Config[:file_cache_path]}/#{installer_config}" diff --git a/recipes/notebook_server.rb b/recipes/notebook_server.rb index f8957c2..39c42be 100644 --- a/recipes/notebook_server.rb +++ b/recipes/notebook_server.rb @@ -10,15 +10,13 @@ include_recipe 'runit::default' anaconda_nbservice 'notebook-server' do - # listen on all interfaces; there will be a warning since security is - # disabled - ip '*' - port '8888' + ip node.anaconda.notebook.ip + port node.anaconda.notebook.port - user 'vagrant' - group 'vagrant' + owner node.anaconda.notebook.owner + group node.anaconda.notebook.group - install_dir '/opt/ipython/server' + install_dir node.anaconda.notebook.install_dir service_action [ :enable, :start ] end diff --git a/recipes/shell_conveniences.rb b/recipes/shell_conveniences.rb index 7575624..e013143 100644 --- a/recipes/shell_conveniences.rb +++ b/recipes/shell_conveniences.rb @@ -14,4 +14,3 @@ :version => node.anaconda.version, }) end - diff --git a/resources/nbservice.rb b/resources/nbservice.rb index 9d8fa48..e0b9757 100644 --- a/resources/nbservice.rb +++ b/resources/nbservice.rb @@ -6,9 +6,9 @@ attribute :service_action, :kind_of => Array attribute :ip, :kind_of => String -attribute :port, :kind_of => String +attribute :port, :kind_of => Fixnum -attribute :user, :kind_of => String +attribute :owner, :kind_of => String attribute :group, :kind_of => String attribute :install_dir, :kind_of => String diff --git a/spec/default_spec.rb b/spec/default_spec.rb index 5d5c87a..70b77d8 100644 --- a/spec/default_spec.rb +++ b/spec/default_spec.rb @@ -6,13 +6,16 @@ context "on #{platform} #{platform_version}" do let(:chef_run) do - ChefSpec::Runner.new( + ChefSpec::SoloRunner.new( platform: platform, # TODO get this working; that is, figure out how to stub this properly #version: platform_version, #step_into: [ 'anaconda_package' ]) do |node| - version: platform_version) do |node| - #node.set['foo']['users'] = users + version: platform_version + ) do |node| + # explicitly set the flavor for tests + # TODO test autodetection of x86 versus x86_64 + node.set['anaconda']['flavor'] = 'x86_64' end end @@ -82,7 +85,7 @@ end it 'has a workaround for python: https://github.com/thmttch/chef-continuum-anaconda/issues/12' do - pending('How do you include a cookbook for testing purposes only? Needs python') + skip('How do you include a cookbook for testing purposes only? Needs python') chef_run.converge('python::default') chef_run.converge(described_recipe) @@ -95,12 +98,14 @@ end describe 'anaconda::default' do + # https://github.com/customink/fauxhai/tree/master/lib/fauxhai/platforms platforms = { - # for whatever reason there's no fauxhai data for 12.10 - 'ubuntu' => [ '12.04', '13.04', '13.10', '14.04' ], - 'debian' => [ '6.0.5' ], - 'centos' => [ '5.8', '6.0', '6.3' ], - 'redhat' => [ '5.8', '6.3' ], + 'ubuntu' => [ '12.04', '14.04', '15.04' ], + # TODO 7.9 and 8.2 were recently released + 'debian' => [ '7.8', '8.1' ], + # TODO 6.7 is the latest + 'centos' => [ '5.11', '6.6', '7.1.1503' ], + 'redhat' => [ '5.9', '6.6', '7.1' ], } platforms.each do |platform, versions| diff --git a/templates/default/sv-ipython-notebook-run.erb b/templates/default/sv-ipython-notebook-run.erb index 13a450b..0580fc2 100644 --- a/templates/default/sv-ipython-notebook-run.erb +++ b/templates/default/sv-ipython-notebook-run.erb @@ -17,7 +17,7 @@ pushd <%= @options[:notebook_dir] %> exec 2>&1 exec \ - <%= "chpst -u #{@options[:user]}" if @options[:user] %> \ + <%= "chpst -u #{@options[:owner]}" if @options[:owner] %> \ <%= @options[:cmd_ipython] %> notebook \ --ipython-dir=<%= @options[:ipython_dir] %> \ --ip=<%= @options[:ip] %> \ diff --git a/test/integration/default/serverspec/default_spec.rb b/test/integration/default/serverspec/default_spec.rb index f4044c0..0df6772 100644 --- a/test/integration/default/serverspec/default_spec.rb +++ b/test/integration/default/serverspec/default_spec.rb @@ -1,5 +1,8 @@ require 'serverspec' -describe command('/opt/anaconda/2.2.0/bin/conda --version') do - its(:stdout) { should match /conda 3.10.0/ } +set :backend, :exec + +describe command('/opt/anaconda/2.3.0/bin/conda --version') do + its(:stderr) { should match /conda 3.14.1/ } + its(:exit_status) { should eq 0 } end