berkshelf-store 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +2 -0
  3. data/Gemfile +5 -0
  4. data/README.md +83 -0
  5. data/Rakefile +44 -0
  6. data/berkshelf-store.gemspec +26 -0
  7. data/bin/berkshelf-store +49 -0
  8. data/lib/berkshelf-store/backends/filesystem.rb +138 -0
  9. data/lib/berkshelf-store/backends.rb +5 -0
  10. data/lib/berkshelf-store/webservice.rb +100 -0
  11. data/lib/berkshelf-store.rb +5 -0
  12. data/test/data/arbo/cookbooks/apache2/1.10.4/data.json +1 -0
  13. data/test/data/arbo/cookbooks/couchbase/1.1.0/data.json +1 -0
  14. data/test/data/arbo/cookbooks/couchbase/1.2.0/data.json +1 -0
  15. data/test/data/catalog.json +69 -0
  16. data/test/data/tarballs/apache2-v1.10.4.tar.gz +0 -0
  17. data/test/data/tarballs/couchbase-v1.1.0.tar.gz +0 -0
  18. data/test/data/tarballs/couchbase-v1.2.0.tar.gz +0 -0
  19. data/test/data/tarballs/not_a_cookbook.tgz +0 -0
  20. data/test/test_berkshelf-store_backends_filesystem.rb +76 -0
  21. data/ui/static/bootstrap/css/bootstrap-theme.css +347 -0
  22. data/ui/static/bootstrap/css/bootstrap-theme.css.map +1 -0
  23. data/ui/static/bootstrap/css/bootstrap-theme.min.css +7 -0
  24. data/ui/static/bootstrap/css/bootstrap.css +5785 -0
  25. data/ui/static/bootstrap/css/bootstrap.css.map +1 -0
  26. data/ui/static/bootstrap/css/bootstrap.min.css +7 -0
  27. data/ui/static/bootstrap/fonts/glyphicons-halflings-regular.eot +0 -0
  28. data/ui/static/bootstrap/fonts/glyphicons-halflings-regular.svg +229 -0
  29. data/ui/static/bootstrap/fonts/glyphicons-halflings-regular.ttf +0 -0
  30. data/ui/static/bootstrap/fonts/glyphicons-halflings-regular.woff +0 -0
  31. data/ui/static/bootstrap/js/bootstrap.js +1951 -0
  32. data/ui/static/bootstrap/js/bootstrap.min.js +6 -0
  33. data/ui/static/jquery/jquery.min.js +4 -0
  34. data/ui/static/jquery_file_upload/CONTRIBUTING.md +42 -0
  35. data/ui/static/jquery_file_upload/Gruntfile.js +37 -0
  36. data/ui/static/jquery_file_upload/README.md +123 -0
  37. data/ui/static/jquery_file_upload/angularjs.html +211 -0
  38. data/ui/static/jquery_file_upload/basic-plus.html +226 -0
  39. data/ui/static/jquery_file_upload/basic.html +136 -0
  40. data/ui/static/jquery_file_upload/blueimp-file-upload.jquery.json +50 -0
  41. data/ui/static/jquery_file_upload/bower.json +85 -0
  42. data/ui/static/jquery_file_upload/cors/postmessage.html +75 -0
  43. data/ui/static/jquery_file_upload/cors/result.html +24 -0
  44. data/ui/static/jquery_file_upload/css/demo-ie8.css +21 -0
  45. data/ui/static/jquery_file_upload/css/demo.css +67 -0
  46. data/ui/static/jquery_file_upload/css/jquery.fileupload-noscript.css +22 -0
  47. data/ui/static/jquery_file_upload/css/jquery.fileupload-ui-noscript.css +17 -0
  48. data/ui/static/jquery_file_upload/css/jquery.fileupload-ui.css +57 -0
  49. data/ui/static/jquery_file_upload/css/jquery.fileupload.css +36 -0
  50. data/ui/static/jquery_file_upload/css/style.css +15 -0
  51. data/ui/static/jquery_file_upload/img/loading.gif +0 -0
  52. data/ui/static/jquery_file_upload/img/progressbar.gif +0 -0
  53. data/ui/static/jquery_file_upload/index.html +255 -0
  54. data/ui/static/jquery_file_upload/jquery-ui.html +250 -0
  55. data/ui/static/jquery_file_upload/js/app.js +101 -0
  56. data/ui/static/jquery_file_upload/js/cors/jquery.postmessage-transport.js +117 -0
  57. data/ui/static/jquery_file_upload/js/cors/jquery.xdr-transport.js +86 -0
  58. data/ui/static/jquery_file_upload/js/jquery.fileupload-angular.js +429 -0
  59. data/ui/static/jquery_file_upload/js/jquery.fileupload-audio.js +106 -0
  60. data/ui/static/jquery_file_upload/js/jquery.fileupload-image.js +315 -0
  61. data/ui/static/jquery_file_upload/js/jquery.fileupload-jquery-ui.js +152 -0
  62. data/ui/static/jquery_file_upload/js/jquery.fileupload-process.js +172 -0
  63. data/ui/static/jquery_file_upload/js/jquery.fileupload-ui.js +699 -0
  64. data/ui/static/jquery_file_upload/js/jquery.fileupload-validate.js +119 -0
  65. data/ui/static/jquery_file_upload/js/jquery.fileupload-video.js +106 -0
  66. data/ui/static/jquery_file_upload/js/jquery.fileupload.js +1426 -0
  67. data/ui/static/jquery_file_upload/js/jquery.iframe-transport.js +214 -0
  68. data/ui/static/jquery_file_upload/js/main.js +75 -0
  69. data/ui/static/jquery_file_upload/js/vendor/jquery.ui.widget.js +530 -0
  70. data/ui/static/jquery_file_upload/package.json +54 -0
  71. data/ui/static/jquery_file_upload/server/gae-go/app/main.go +296 -0
  72. data/ui/static/jquery_file_upload/server/gae-go/app.yaml +12 -0
  73. data/ui/static/jquery_file_upload/server/gae-go/static/favicon.ico +0 -0
  74. data/ui/static/jquery_file_upload/server/gae-go/static/robots.txt +2 -0
  75. data/ui/static/jquery_file_upload/server/gae-python/app.yaml +16 -0
  76. data/ui/static/jquery_file_upload/server/gae-python/main.py +170 -0
  77. data/ui/static/jquery_file_upload/server/gae-python/static/favicon.ico +0 -0
  78. data/ui/static/jquery_file_upload/server/gae-python/static/robots.txt +2 -0
  79. data/ui/static/jquery_file_upload/server/node/package.json +41 -0
  80. data/ui/static/jquery_file_upload/server/node/server.js +292 -0
  81. data/ui/static/jquery_file_upload/server/php/UploadHandler.php +1330 -0
  82. data/ui/static/jquery_file_upload/server/php/index.php +15 -0
  83. data/ui/static/jquery_file_upload/test/index.html +166 -0
  84. data/ui/static/jquery_file_upload/test/test.js +1288 -0
  85. data/ui/views/catalog.erb +20 -0
  86. data/ui/views/doc.erb +23 -0
  87. data/ui/views/layout.erb +47 -0
  88. data/ui/views/upload.erb +46 -0
  89. metadata +210 -0
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ OWQ4NTk2YzFkM2Q5NDg5Y2Y1YTRhODIxYzM1ZjIwNDM1ZjkzYzVjNg==
5
+ data.tar.gz: !binary |-
6
+ MmMzMTQ2N2ZlMTQ4MmVkMTg1MDA0MWUwODYyNmM1ZWFjNDMyODVkMw==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ MzAxMzljYTA1MWQ4N2I1ZWJkMjhmNjU5MWFjMThkYTZhNTJmMGRiMmM5MjI1
10
+ NjNjMWY3YjVhODMwNTZjNDlkNzQ1OTcxNjFkZTAyNGI0OGQwNDYwNTQzZTc2
11
+ NzI5ZWNlNDNiYThlNWU0ODE5NWQ2ZjRlYjRhZjljNDJlNGJmZTQ=
12
+ data.tar.gz: !binary |-
13
+ YWYzYjMyZjFlZmIzOTY5NzJmOWQ2OWI4MjZjNzNmZjRhNTdjZmY3YmM2NTgy
14
+ MTk4NTU0ZGY0MTk5OWZlOTczYzcxMDI5NDRiNWM5MWI0ZDVkOTAxMmU3NWQx
15
+ N2NjMzNiZTQ5NDc5ODAxMTEzZjI3YjhhY2EyYWE5NzZkNTAzNDc=
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ test/tmp/**
2
+ ui/static/**
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # A sample Gemfile
2
+ source "https://rubygems.org"
3
+
4
+ gemspec
5
+
data/README.md ADDED
@@ -0,0 +1,83 @@
1
+ berkshelf-store
2
+ ===============
3
+
4
+ A cookbook store compatible with berkshelf API.
5
+
6
+ Currently it is a simple webservice :
7
+ * POST /v1/cookbooks/$Name/$Version
8
+ * cookbook param contains tgz
9
+ * GET /v1/universe
10
+ * this is berkshelf API
11
+ * GET /v1/cookbooks/$Name/$Version/$Name-$Version.tgz
12
+ * this is how berkshelf gets the cookbook
13
+
14
+ Storage is a simple directory tree (easy to backup)
15
+
16
+ Status
17
+ ------
18
+
19
+ work in progress...
20
+
21
+ It is my first ruby project, any advise is welcome :)
22
+
23
+ Why would I need this ?
24
+ -----------------------
25
+
26
+ If you have private cookbooks or a validation process for public cookboks, you need an internal storage.
27
+
28
+ If you use chef-solo, knife-solo and/or more than one chef-server, you'll need a central catalog of your cookbooks.
29
+
30
+ Yes there is berkshelf-api, but it needs a chef server :
31
+ * A litle overkill if you do no plan to really use it.
32
+ * not a uniform service
33
+ * upload via chef
34
+ * read via berkshelf
35
+
36
+ Install
37
+ -------
38
+
39
+ gem build berkshelf-store.gemspec
40
+ gem install berkshelf-store-*.gem
41
+
42
+
43
+ Usage
44
+ -----
45
+
46
+ ### Launch the deamon
47
+
48
+ Usage: berkshelf-store.rb [options]
49
+ -D, --datadir DIRECTORY Data directory (default: ./datadir)
50
+ -T, --tmpdir DIRECTORY Tmp directory (default: ./tmpdir)
51
+ -b, --bind IP bind IP (default: 127.0.0.1)
52
+ -p, --port PORT port to listen on (default: 80)
53
+ -l, --logger TYPE file, syslog, stderr (default: syslog)
54
+ -L, --logger-conf TYPE file: filename, syslog: program.facility, stderr n/a (default: berkshelf-store.daemon)
55
+
56
+ Example:
57
+
58
+ berkshelf-store -D /var/lib/berkshelf-store -T /var/tmp/berkshelf-store --bind 0.0.0.0 -l stderr
59
+
60
+ ### upload some cookbooks
61
+
62
+ curl -F cookbook=@/path/to/the/cookbook.tgz http://localhost/v1/cookbooks/cookbookname/cookbookversion
63
+
64
+ ### use it with berkshelf
65
+
66
+ in the berkfile:
67
+
68
+ source "http://localhost/v1"
69
+
70
+ cookbook "cookbookname"
71
+
72
+ TODO:
73
+ -----
74
+
75
+ by priority
76
+
77
+ - more Comments and tests
78
+ - cli (knife or beks plugin) for uploading
79
+ - Auth
80
+ - ACL (limit uploads by cookbook/users/groups)
81
+ - UI
82
+ - multi-tenancy ?
83
+ - clusterized/cloudified backend (mongo, S3, whatelse ?)
data/Rakefile ADDED
@@ -0,0 +1,44 @@
1
+ require 'rake/testtask'
2
+ require 'net/http'
3
+
4
+ STATICDIR='ui/static'
5
+
6
+ desc "Run tests"
7
+ Rake::TestTask.new do |t|
8
+ t.libs << 'test'
9
+ t.test_files = FileList['test/test*.rb']
10
+ t.verbose = true
11
+ end
12
+
13
+ task :default => :build
14
+
15
+ task :build => [ :test, :vendor ] do
16
+ system "gem build berkshelf-store.gemspec"
17
+ end
18
+
19
+ directory "#{STATICDIR}"
20
+ task :vendor => [ "#{STATICDIR}/bootstrap", "#{STATICDIR}/jquery/jquery.min.js", "#{STATICDIR}/jquery_file_upload" ] do
21
+ puts "Vendored"
22
+ end
23
+
24
+ desc "Get bootstrap"
25
+ directory "#{STATICDIR}/bootstrap" do
26
+ version = "3.1.1"
27
+ system "wget https://github.com/twbs/bootstrap/releases/download/v#{version}/bootstrap-#{version}-dist.zip -O #{STATICDIR}/bootstrap.zip"
28
+ system "cd #{STATICDIR}; unzip bootstrap.zip; mv bootstrap-#{version}-dist bootstrap; rm bootstrap.zip"
29
+ end
30
+
31
+ desc "Get jquery"
32
+ file "#{STATICDIR}/jquery/jquery.min.js" do
33
+ version = "1.11.1"
34
+ system "mkdir #{STATICDIR}/jquery"
35
+ system "wget http://code.jquery.com/jquery-#{version}.min.js -O #{STATICDIR}/jquery/jquery.min.js"
36
+ end
37
+
38
+ desc "Get jquery file upload"
39
+ directory "#{STATICDIR}/jquery_file_upload" do
40
+ version = "9.5.7"
41
+ system "wget https://github.com/blueimp/jQuery-File-Upload/archive/#{version}.tar.gz -O #{STATICDIR}/jquery_file_upload.tgz"
42
+ system "cd #{STATICDIR}; tar xvzf jquery_file_upload.tgz; mv jQuery-File-Upload-#{version} jquery_file_upload; rm jquery_file_upload.tgz"
43
+ end
44
+
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "berkshelf-store"
6
+ s.version = "0.2.0"
7
+ s.authors = ["Guillaume Zitta"]
8
+ s.email = ["github.guillaume@zitta.fr"]
9
+ s.homepage = "https://github.com/gza/berkshelf-store"
10
+ s.summary = "A cookbook store based on the berkshelf API"
11
+ s.description = s.summary
12
+
13
+ s.rubyforge_project = "berkshelf-store"
14
+
15
+ s.files = `git ls-files`.split("\n") + Dir.glob("{ui}/**/*")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_dependency 'syslog-logger'
21
+ s.add_dependency 'ridley'
22
+ s.add_dependency 'sinatra', '>=1.4.5'
23
+ s.add_dependency 'sinatra-contrib', '>=1.4.2'
24
+
25
+ s.add_development_dependency 'rake'
26
+ end
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+ $:.push File.expand_path("../../lib", __FILE__)
3
+
4
+ require 'optparse'
5
+ require 'berkshelf-store'
6
+
7
+ options = {
8
+ datadir:"./datadir",
9
+ tmpdir:"./tmpdir",
10
+ bind:"127.0.0.1",
11
+ port:"80",
12
+ logger_type:"syslog",
13
+ logger_conf:"berkshelf-store.daemon"
14
+ }
15
+
16
+ OptionParser.new do |opts|
17
+ opts.banner = "Usage: berkshelf-store.rb [options]"
18
+
19
+ opts.on("-D", "--datadir DIRECTORY", "Data directory (default: #{options[:datadir]})") do |d|
20
+ options[:datadir] = d
21
+ end
22
+
23
+ opts.on("-T", "--tmpdir DIRECTORY", "Tmp directory (default: #{options[:tmpdir]})") do |t|
24
+ options[:tmpdir] = t
25
+ end
26
+
27
+ opts.on("-b", "--bind IP", "bind IP (default: #{options[:bind]})") do |ip|
28
+ options[:bind] = ip
29
+ end
30
+
31
+ opts.on("-p", "--port PORT", "port to listen on (default: #{options[:port]})") do |p|
32
+ options[:port] = p
33
+ end
34
+
35
+ opts.on("-l", "--logger TYPE", "file, syslog, stderr (default: #{options[:logger_type]})") do |l|
36
+ options[:logger_type] = l
37
+ end
38
+
39
+ opts.on("-L", "--logger-conf TYPE", "file: filename, syslog: program.facility, stderr n/a (default: #{options[:logger_conf]})") do |lc|
40
+ options[:logger_conf] = lc
41
+ end
42
+ end.parse!
43
+
44
+ #The only way I found to pass options to configure
45
+ ENV['LOGGER_TYPE'] ||= options.delete(:logger_type)
46
+ ENV['LOGGER_CONF'] ||= options.delete(:logger_conf)
47
+
48
+ #remaining options will be available as settings
49
+ BerkshelfStore::Webservice.run!(options)
@@ -0,0 +1,138 @@
1
+ require 'digest'
2
+ require 'json'
3
+ require 'fileutils'
4
+ require 'ridley'
5
+
6
+ module BerkshelfStore::Backends
7
+ class Filesystem
8
+
9
+ @error = ''
10
+
11
+ def initialize(path, tmp)
12
+ @path = path
13
+ @tmp = tmp
14
+ end
15
+
16
+ def check_filename(filename)
17
+ #do minimal checks
18
+ true
19
+ end
20
+
21
+ def store(content, name, version)
22
+ data = {}
23
+
24
+ digest = Digest::SHA256.hexdigest(content)
25
+ tmp_dir = "#{@tmp}/#{digest}"
26
+
27
+ FileUtils.mkdir_p "#{tmp_dir}/cookbook"
28
+
29
+ #extract cookbook
30
+ if write_tmp_file("#{tmp_dir}/cookbook.tgz", content)
31
+ cmd = "tar --gzip --extract --file=\"#{tmp_dir}/cookbook.tgz\" -C \"#{tmp_dir}/cookbook\""
32
+ %x{#{cmd}}
33
+
34
+ if $?.exitstatus != 0
35
+ return {"fail" => "Failed to extract metadata.rb from tarball"}
36
+ end
37
+ else
38
+ return {"fail" => "Unable to write cookbook #{tmp_dir}/cookbook.tgz"}
39
+ end
40
+
41
+ #locate check cookbook
42
+ search_root = Dir["#{tmp_dir}/cookbook/*/metadata.rb"]
43
+ if search_root.size != 1
44
+ return {"fail" => "tgz don't contains one and only on */metadata.rb"}
45
+ end
46
+ cookbook_dir = File.dirname(search_root[0])
47
+
48
+ #Extract information
49
+ begin
50
+ cookbook = Ridley::Chef::Cookbook.from_path(cookbook_dir)
51
+ data = cookbook_data(cookbook)
52
+ rescue Exception => e
53
+ return {"fail" => "Information extraction failed #{e}"}
54
+ end
55
+
56
+ begin
57
+ data_dir = "#{@path}/#{name}/#{version}"
58
+ FileUtils.mkdir_p "#{data_dir}"
59
+ rescue SystemCallError => e
60
+ return {"fail" => "#{data_dir} creation failed #{e}"}
61
+ end
62
+
63
+ begin
64
+ json_file = File.open("#{data_dir}/data.json", "w")
65
+ json_file.write(data.to_json)
66
+ json_file.close
67
+ rescue Exception => e
68
+ return {"fail" => "#{data_dir}/data.json creation failed #{e}"}
69
+ end
70
+
71
+ begin
72
+ File.rename("#{tmp_dir}/cookbook.tgz", "#{data_dir}/#{name}-#{version}.tgz")
73
+ rescue Exception => e
74
+ return {"fail" => "tarball store failed #{e}"}
75
+ end
76
+
77
+ return data
78
+ end
79
+
80
+ def cookbook_data(cookbook)
81
+ platforms = cookbook.metadata.platforms || Hash.new
82
+ dependencies = cookbook.metadata.dependencies || Hash.new
83
+
84
+ name = cookbook.cookbook_name.to_s
85
+ version = cookbook.version.to_s
86
+
87
+ path = "/#{name}/#{version}/#{name}-#{version}.tgz"
88
+
89
+ retval = {
90
+ "name" => name,
91
+ "version" => version,
92
+ "data" => {
93
+ "endpoint_priority" => 0,
94
+ "platforms" => platforms,
95
+ "dependencies" => dependencies,
96
+ "location_type" => 'uri',
97
+ "location_path" => path
98
+ }
99
+ }
100
+ return retval
101
+ end
102
+
103
+ def write_tmp_file(name, content)
104
+ begin
105
+ tarfile = File.open("#{name}", "w")
106
+ tarfile.write(content)
107
+ rescue IOError => e
108
+ @error="Failed to write temp file #{name}"
109
+ return false
110
+ ensure
111
+ tarfile.close unless tarfile == nil
112
+ end
113
+ end
114
+
115
+ def last_error
116
+ @error
117
+ end
118
+
119
+ def get_json(name, version)
120
+ File.open("#{@path}/#{name}/#{version}/data.json", "r").read
121
+ end
122
+
123
+ def get_tarball(name, version)
124
+ File.open("#{@path}/#{name}/#{version}/#{name}-#{version}.tgz").read
125
+ end
126
+
127
+ def get_catalog(prefix)
128
+ retval = {}
129
+ Dir["#{@path}/*/*/data.json"].each do |json_file|
130
+ data = JSON.parse(File.read("#{json_file}"))
131
+ data['data']['location_path'] = "#{prefix}#{data['data']['location_path']}"
132
+ retval[data['name']] ||= Hash.new
133
+ retval[data['name']][data['version']] = data['data']
134
+ end
135
+ retval
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,5 @@
1
+ module BerkshelfStore
2
+ module Backends
3
+ autoload :Filesystem, 'berkshelf-store/backends/filesystem'
4
+ end
5
+ end
@@ -0,0 +1,100 @@
1
+ require 'sinatra/base'
2
+ require 'sinatra/json'
3
+ require 'syslog-logger'
4
+ require 'logger'
5
+
6
+ #require 'berkshelf-store'
7
+ ::Logger.class_eval { alias :write :'<<' }
8
+ ::Logger::Syslog.class_eval { alias :write :'<<' }
9
+
10
+ module BerkshelfStore
11
+ class Webservice < Sinatra::Base
12
+ helpers Sinatra::JSON
13
+
14
+ helpers do
15
+ def logger
16
+ settings.logger
17
+ end
18
+ end
19
+
20
+ configure do
21
+ logger_type = ENV['LOGGER_TYPE'].to_s
22
+ logger_conf = ENV['LOGGER_CONF'].to_s
23
+ if logger_type == "file"
24
+ logger = Logger.new(File.open("#{logger_conf}", 'a'))
25
+ elsif logger_type == "stderr"
26
+ logger = Logger.new(STDERR)
27
+ elsif logger_type == "syslog"
28
+ programname = logger_conf.split(".")[0]
29
+ facility = eval("Syslog::LOG_#{logger_conf.to_s.split(".")[1].upcase}")
30
+ logger = Logger::Syslog.new(programname, facility)
31
+ end
32
+ use ::Rack::CommonLogger, logger
33
+ set :logger, logger
34
+
35
+ #static files (UI) stuff
36
+ #et :public_folder, BerkshelfStore::ROOT + '/www/static'
37
+
38
+ end
39
+ set :prefix, "/"
40
+ set :public_folder, BerkshelfStore::ROOT + '/ui/static'
41
+ set :views, BerkshelfStore::ROOT + '/ui/views'
42
+
43
+
44
+ get "/ping" do
45
+ logger.info 'ping'
46
+ json({'info' => 'berkshelf-store',
47
+ 'version' => 'it would be nice to show it :)',
48
+ 'status' => 'seems to work :)'})
49
+ end
50
+
51
+ get "/v1/universe" do
52
+ cookbooks_url_prefix = "#{request.base_url}/v1/cookbooks"
53
+ storage = BerkshelfStore::Backends::Filesystem.new(settings.datadir, settings.tmpdir)
54
+ json(storage.get_catalog(cookbooks_url_prefix))
55
+ end
56
+
57
+ get "/v1/cookbooks/:name/:version/:filename" do
58
+ if params[:filename] == "#{params[:name]}-#{params[:version]}.tgz"
59
+ storage = BerkshelfStore::Backends::Filesystem.new(settings.datadir, settings.tmpdir)
60
+ storage.get_tarball(params[:name],params[:version])
61
+ else
62
+ halt 400, json({'fail' => 'cookbook name should be name-version.tgz'})
63
+ end
64
+ end
65
+
66
+ post "/v1/cookbooks/:name/:version" do
67
+ if params.key?("cookbook") && params.key?("name") && params.key?("version")
68
+ storage = BerkshelfStore::Backends::Filesystem.new(settings.datadir, settings.tmpdir)
69
+ cookbook_data = storage.store(params["cookbook"][:tempfile].read, params[:name], params[:version])
70
+ if cookbook_data.key?('name')
71
+ json cookbook_data
72
+ else
73
+ halt 500, json(cookbook_data)
74
+ end
75
+ else
76
+ halt 400, json({'fail' => 'Wrong parameters'})
77
+ end
78
+ end
79
+
80
+ get "/" do
81
+ redirect "/index.html"
82
+ end
83
+
84
+ get "/:name.html" do
85
+ @site_prefix="#{request.base_url}"
86
+ @ws_prefix="/v1"
87
+ @active="#{params[:name]}"
88
+ if params[:name] == 'index'
89
+ erb :catalog
90
+ elsif params[:name] == 'upload'
91
+ erb :upload
92
+ elsif params[:name] == 'doc'
93
+ erb :doc
94
+ else
95
+ halt 404, "<h1>page #{params[:name]}.html not found</h1>"
96
+ end
97
+ end
98
+
99
+ end
100
+ end
@@ -0,0 +1,5 @@
1
+ module BerkshelfStore
2
+ ROOT = File.expand_path("../..", __FILE__)
3
+ autoload :Backends, 'berkshelf-store/backends'
4
+ autoload :Webservice, 'berkshelf-store/webservice'
5
+ end
@@ -0,0 +1 @@
1
+ {"name":"apache2","version":"1.10.4","data":{"endpoint_priority":0,"platforms":{"amazon":">= 0.0.0","arch":">= 0.0.0","centos":">= 0.0.0","debian":">= 0.0.0","fedora":">= 0.0.0","freebsd":">= 0.0.0","redhat":">= 0.0.0","scientific":">= 0.0.0","ubuntu":">= 0.0.0"},"dependencies":{"iptables":">= 0.0.0","logrotate":">= 0.0.0","pacman":">= 0.0.0"},"location_type":"uri","location_path":"/apache2/1.10.4/apache2-1.10.4.tgz"}}
@@ -0,0 +1 @@
1
+ {"name":"couchbase","version":"1.1.0","data":{"endpoint_priority":0,"platforms":{"debian":">= 0.0.0","ubuntu":">= 0.0.0","centos":">= 0.0.0","redhat":">= 0.0.0","oracle":">= 0.0.0","amazon":">= 0.0.0","scientific":">= 0.0.0","windows":">= 0.0.0"},"dependencies":{"apt":">= 0.0.0","openssl":">= 0.0.0","windows":">= 0.0.0","yum":">= 0.0.0"},"location_type":"uri","location_path":"/couchbase/1.1.0/couchbase-1.1.0.tgz"}}
@@ -0,0 +1 @@
1
+ {"name":"couchbase","version":"1.2.0","data":{"endpoint_priority":0,"platforms":{"debian":">= 0.0.0","ubuntu":">= 0.0.0","centos":">= 0.0.0","redhat":">= 0.0.0","oracle":">= 0.0.0","amazon":">= 0.0.0","scientific":">= 0.0.0","windows":">= 0.0.0"},"dependencies":{"apt":">= 0.0.0","openssl":">= 0.0.0","windows":">= 0.0.0","yum":">= 0.0.0"},"location_type":"uri","location_path":"/couchbase/1.2.0/couchbase-1.2.0.tgz"}}
@@ -0,0 +1,69 @@
1
+ {
2
+ "apache2": {
3
+ "1.10.4": {
4
+ "dependencies": {
5
+ "iptables": ">= 0.0.0",
6
+ "logrotate": ">= 0.0.0",
7
+ "pacman": ">= 0.0.0"
8
+ },
9
+ "endpoint_priority": 0,
10
+ "location_path": "http://localhost/apache2/1.10.4/apache2-1.10.4.tgz",
11
+ "location_type": "uri",
12
+ "platforms": {
13
+ "amazon": ">= 0.0.0",
14
+ "arch": ">= 0.0.0",
15
+ "centos": ">= 0.0.0",
16
+ "debian": ">= 0.0.0",
17
+ "fedora": ">= 0.0.0",
18
+ "freebsd": ">= 0.0.0",
19
+ "redhat": ">= 0.0.0",
20
+ "scientific": ">= 0.0.0",
21
+ "ubuntu": ">= 0.0.0"
22
+ }
23
+ }
24
+ },
25
+ "couchbase": {
26
+ "1.1.0": {
27
+ "dependencies": {
28
+ "apt": ">= 0.0.0",
29
+ "openssl": ">= 0.0.0",
30
+ "windows": ">= 0.0.0",
31
+ "yum": ">= 0.0.0"
32
+ },
33
+ "endpoint_priority": 0,
34
+ "location_path": "http://localhost/couchbase/1.1.0/couchbase-1.1.0.tgz",
35
+ "location_type": "uri",
36
+ "platforms": {
37
+ "amazon": ">= 0.0.0",
38
+ "centos": ">= 0.0.0",
39
+ "debian": ">= 0.0.0",
40
+ "oracle": ">= 0.0.0",
41
+ "redhat": ">= 0.0.0",
42
+ "scientific": ">= 0.0.0",
43
+ "ubuntu": ">= 0.0.0",
44
+ "windows": ">= 0.0.0"
45
+ }
46
+ },
47
+ "1.2.0": {
48
+ "dependencies": {
49
+ "apt": ">= 0.0.0",
50
+ "openssl": ">= 0.0.0",
51
+ "windows": ">= 0.0.0",
52
+ "yum": ">= 0.0.0"
53
+ },
54
+ "endpoint_priority": 0,
55
+ "location_path": "http://localhost/couchbase/1.2.0/couchbase-1.2.0.tgz",
56
+ "location_type": "uri",
57
+ "platforms": {
58
+ "amazon": ">= 0.0.0",
59
+ "centos": ">= 0.0.0",
60
+ "debian": ">= 0.0.0",
61
+ "oracle": ">= 0.0.0",
62
+ "redhat": ">= 0.0.0",
63
+ "scientific": ">= 0.0.0",
64
+ "ubuntu": ">= 0.0.0",
65
+ "windows": ">= 0.0.0"
66
+ }
67
+ }
68
+ }
69
+ }
@@ -0,0 +1,76 @@
1
+ require 'json'
2
+ require 'test/unit'
3
+ require 'berkshelf-store'
4
+
5
+ class BerkshelfRepoBackendsFilesystemTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @test_dir = File.dirname(__FILE__)
9
+ @tarballs = "#{@test_dir}/data/tarballs"
10
+ @dataarbo = "#{@test_dir}/data/arbo"
11
+ @tmp="#{@test_dir}/tmp/tmp"
12
+ @path="#{@test_dir}/tmp/path"
13
+
14
+ #test_cases
15
+ @test_case = Hash.new
16
+ @test_case[:couchbase_1_2_0] = Hash.new
17
+ @test_case[:couchbase_1_2_0][:name] = 'couchbase'
18
+ @test_case[:couchbase_1_2_0][:version] = '1.2.0'
19
+ @test_case[:couchbase_1_2_0][:content] = File.read("#{@tarballs}/couchbase-v1.2.0.tar.gz")
20
+ @test_case[:couchbase_1_2_0][:json] = File.read("#{@dataarbo}/cookbooks/couchbase/1.2.0/data.json")
21
+ end
22
+
23
+ def clean
24
+ FileUtils.rm_rf(@tmp)
25
+ FileUtils.mkdir_p(@tmp)
26
+ FileUtils.rm_rf(@path)
27
+ FileUtils.mkdir_p(@path)
28
+ end
29
+
30
+ def test_store
31
+ clean()
32
+
33
+ @test_case.values.each do |cookbook|
34
+ repo=BerkshelfStore::Backends::Filesystem.new(@path,@tmp)
35
+
36
+ cbdir = "#{@path}/#{cookbook[:name]}/#{cookbook[:version]}"
37
+ #Must not exists before
38
+ assert(! File.exists?(cbdir))
39
+
40
+ result_store = repo.store(cookbook[:content], cookbook[:name], cookbook[:version])
41
+
42
+ assert(File.exists?(cbdir))
43
+ assert(File.exists?("#{cbdir}/#{cookbook[:name]}-#{cookbook[:version]}.tgz"))
44
+ assert(File.exists?("#{cbdir}/data.json"))
45
+
46
+ assert( result_store )
47
+
48
+ generated_data = JSON.parse(File.read("#{cbdir}/data.json"))
49
+ control_data = JSON.parse(cookbook[:json])
50
+ assert_equal(control_data, generated_data)
51
+ end
52
+ end
53
+
54
+ def test_store_bad_tgz
55
+ clean()
56
+ repo=BerkshelfStore::Backends::Filesystem.new(@path,@tmp)
57
+ result_store = repo.store("this is not tgz data, hi hi", "toto", "0.0.0")
58
+ assert( result_store.key?('fail') )
59
+ end
60
+
61
+ def test_store_not_cookbook_tgz
62
+ clean()
63
+ repo=BerkshelfStore::Backends::Filesystem.new(@path,@tmp)
64
+ result_store = repo.store(File.read("#{@tarballs}/not_a_cookbook.tgz"), "toto", "0.0.0")
65
+ assert( result_store.key?('fail') )
66
+ end
67
+
68
+ def test_get_catalog
69
+ clean()
70
+
71
+ repo=BerkshelfStore::Backends::Filesystem.new("#{@dataarbo}/cookbooks", @tmp)
72
+ generated_data = repo.get_catalog("http://localhost")
73
+ control_data = JSON.parse(File.read("#{@test_dir}/data/catalog.json"))
74
+ assert_equal(control_data, generated_data)
75
+ end
76
+ end