minimart 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +21 -0
- data/.rspec +3 -0
- data/.travis.yml +13 -0
- data/Gemfile +3 -0
- data/README.md +198 -0
- data/Rakefile +45 -0
- data/bin/minimart +4 -0
- data/lib/minimart.rb +15 -0
- data/lib/minimart/cli.rb +93 -0
- data/lib/minimart/commands/mirror.rb +30 -0
- data/lib/minimart/commands/web.rb +91 -0
- data/lib/minimart/configuration.rb +46 -0
- data/lib/minimart/cookbook.rb +173 -0
- data/lib/minimart/download/cookbook.rb +70 -0
- data/lib/minimart/download/git_cache.rb +60 -0
- data/lib/minimart/download/git_repository.rb +41 -0
- data/lib/minimart/error.rb +32 -0
- data/lib/minimart/inventory_requirement/base_requirement.rb +81 -0
- data/lib/minimart/inventory_requirement/git_requirement.rb +87 -0
- data/lib/minimart/inventory_requirement/git_requirements_builder.rb +101 -0
- data/lib/minimart/inventory_requirement/local_path_requirement.rb +45 -0
- data/lib/minimart/inventory_requirement/local_requirements_builder.rb +31 -0
- data/lib/minimart/inventory_requirement/supermarket_requirements_builder.rb +35 -0
- data/lib/minimart/mirror.rb +12 -0
- data/lib/minimart/mirror/dependency_graph.rb +73 -0
- data/lib/minimart/mirror/download_metadata.rb +57 -0
- data/lib/minimart/mirror/inventory_builder.rb +143 -0
- data/lib/minimart/mirror/inventory_configuration.rb +74 -0
- data/lib/minimart/mirror/inventory_requirements.rb +104 -0
- data/lib/minimart/mirror/local_store.rb +107 -0
- data/lib/minimart/mirror/source.rb +57 -0
- data/lib/minimart/mirror/source_cookbook.rb +77 -0
- data/lib/minimart/mirror/sources.rb +37 -0
- data/lib/minimart/output.rb +34 -0
- data/lib/minimart/utils/archive.rb +39 -0
- data/lib/minimart/utils/file_helper.rb +34 -0
- data/lib/minimart/utils/http.rb +60 -0
- data/lib/minimart/version.rb +3 -0
- data/lib/minimart/web.rb +10 -0
- data/lib/minimart/web/cookbook_show_page_generator.rb +78 -0
- data/lib/minimart/web/cookbooks.rb +83 -0
- data/lib/minimart/web/dashboard_generator.rb +46 -0
- data/lib/minimart/web/html_generator.rb +52 -0
- data/lib/minimart/web/markdown_parser.rb +47 -0
- data/lib/minimart/web/template_helper.rb +132 -0
- data/lib/minimart/web/universe_generator.rb +109 -0
- data/minimart.gemspec +36 -0
- data/spec/fixtures/sample_cookbook.tar.gz +0 -0
- data/spec/fixtures/sample_cookbook/Berksfile +3 -0
- data/spec/fixtures/sample_cookbook/CHANGELOG.md +3 -0
- data/spec/fixtures/sample_cookbook/Gemfile +16 -0
- data/spec/fixtures/sample_cookbook/LICENSE +3 -0
- data/spec/fixtures/sample_cookbook/README.md +42 -0
- data/spec/fixtures/sample_cookbook/Thorfile +5 -0
- data/spec/fixtures/sample_cookbook/Vagrantfile +90 -0
- data/spec/fixtures/sample_cookbook/chefignore +94 -0
- data/spec/fixtures/sample_cookbook/metadata.rb +9 -0
- data/spec/fixtures/sample_cookbook/recipes/default.rb +8 -0
- data/spec/fixtures/sample_inventory.yml +16 -0
- data/spec/fixtures/simple_git_inventory.yml +8 -0
- data/spec/fixtures/simple_inventory.yml +6 -0
- data/spec/fixtures/simple_local_path_inventory.yml +5 -0
- data/spec/fixtures/universe.json +42 -0
- data/spec/fixtures/vcr_cassettes/local_path_cookbooks.yml +3316 -0
- data/spec/fixtures/vcr_cassettes/location_specific_cookbooks.yml +3316 -0
- data/spec/fixtures/vcr_cassettes/supermarket_cookbooks_graph.yml +905 -0
- data/spec/fixtures/vcr_cassettes/supermarket_cookbooks_installing_cookbooks.yml +4218 -0
- data/spec/lib/minimart/cli_spec.rb +104 -0
- data/spec/lib/minimart/commands/mirror_spec.rb +37 -0
- data/spec/lib/minimart/commands/web_spec.rb +75 -0
- data/spec/lib/minimart/configuration_spec.rb +54 -0
- data/spec/lib/minimart/cookbook_spec.rb +137 -0
- data/spec/lib/minimart/download/cookbook_spec.rb +135 -0
- data/spec/lib/minimart/download/git_cache_spec.rb +69 -0
- data/spec/lib/minimart/download/git_repository_spec.rb +39 -0
- data/spec/lib/minimart/error_spec.rb +18 -0
- data/spec/lib/minimart/inventory_requirement/base_requirement_spec.rb +38 -0
- data/spec/lib/minimart/inventory_requirement/git_requirement_spec.rb +92 -0
- data/spec/lib/minimart/inventory_requirement/git_requirements_builder_spec.rb +130 -0
- data/spec/lib/minimart/inventory_requirement/local_path_requirement_spec.rb +35 -0
- data/spec/lib/minimart/inventory_requirement/local_requirements_builder_spec.rb +33 -0
- data/spec/lib/minimart/inventory_requirement/supermarket_requirements_builder_spec.rb +69 -0
- data/spec/lib/minimart/mirror/dependency_graph_spec.rb +123 -0
- data/spec/lib/minimart/mirror/download_metadata_spec.rb +73 -0
- data/spec/lib/minimart/mirror/inventory_builder_spec.rb +195 -0
- data/spec/lib/minimart/mirror/inventory_configuration_spec.rb +86 -0
- data/spec/lib/minimart/mirror/inventory_requirements_spec.rb +78 -0
- data/spec/lib/minimart/mirror/local_store_spec.rb +64 -0
- data/spec/lib/minimart/mirror/source_spec.rb +54 -0
- data/spec/lib/minimart/mirror/sources_spec.rb +50 -0
- data/spec/lib/minimart/output_spec.rb +29 -0
- data/spec/lib/minimart/utils/archive_spec.rb +38 -0
- data/spec/lib/minimart/utils/file_helper_spec.rb +43 -0
- data/spec/lib/minimart/utils/http_spec.rb +37 -0
- data/spec/lib/minimart/web/cookbook_show_page_generator_spec.rb +101 -0
- data/spec/lib/minimart/web/cookbooks_spec.rb +70 -0
- data/spec/lib/minimart/web/dashboard_generator_spec.rb +33 -0
- data/spec/lib/minimart/web/html_generator_spec.rb +34 -0
- data/spec/lib/minimart/web/markdown_parser_spec.rb +54 -0
- data/spec/lib/minimart/web/template_helper_spec.rb +86 -0
- data/spec/lib/minimart/web/universe_generator_spec.rb +125 -0
- data/spec/spec_helper.rb +35 -0
- data/spec/support/file_system.rb +22 -0
- data/web/_assets/javascripts/app.js +164 -0
- data/web/_assets/javascripts/backbone.min.js +6 -0
- data/web/_assets/javascripts/jquery.min.js +4 -0
- data/web/_assets/javascripts/jquery.tabslet.min.js +9 -0
- data/web/_assets/javascripts/manifest.js +5 -0
- data/web/_assets/javascripts/underscore.min.js +5 -0
- data/web/_assets/stylesheets/font-awesome.min.css +4 -0
- data/web/_assets/stylesheets/font-mfizz.css +318 -0
- data/web/_assets/stylesheets/main.css +720 -0
- data/web/_assets/stylesheets/manifest.css +4 -0
- data/web/_assets/stylesheets/normalize.css +427 -0
- data/web/assets/fonts/FontAwesome.otf +0 -0
- data/web/assets/fonts/font-mfizz.eot +0 -0
- data/web/assets/fonts/font-mfizz.svg +1344 -0
- data/web/assets/fonts/font-mfizz.ttf +0 -0
- data/web/assets/fonts/font-mfizz.woff +0 -0
- data/web/assets/fonts/fontawesome-webfont.eot +0 -0
- data/web/assets/fonts/fontawesome-webfont.svg +520 -0
- data/web/assets/fonts/fontawesome-webfont.ttf +0 -0
- data/web/assets/fonts/fontawesome-webfont.woff +0 -0
- data/web/assets/images/header-slim.jpg +0 -0
- data/web/assets/images/icon-search.png +0 -0
- data/web/assets/images/mad-glory-logo.png +0 -0
- data/web/assets/images/main-gradient.png +0 -0
- data/web/assets/images/top-bar-logo.png +0 -0
- data/web/assets/javascripts/application.min.js +5 -0
- data/web/assets/stylesheets/application.min.css +4 -0
- data/web/templates/cookbook_show.erb +96 -0
- data/web/templates/dashboard.erb +81 -0
- data/web/templates/layout.erb +38 -0
- metadata +433 -0
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'minimart/utils/http'
|
2
|
+
|
3
|
+
module Minimart
|
4
|
+
module Mirror
|
5
|
+
|
6
|
+
# Source represents a single remote source to fetch cookbooks from.
|
7
|
+
# Each source is specified in the inventory using the 'sources' key.
|
8
|
+
class Source
|
9
|
+
|
10
|
+
# @return [String] The URL for this source
|
11
|
+
attr_accessor :base_url
|
12
|
+
|
13
|
+
# @param [String] base_url The URL for this source
|
14
|
+
def initialize(base_url)
|
15
|
+
@base_url = base_url
|
16
|
+
end
|
17
|
+
|
18
|
+
# Search through the cookbooks available at this source, and return
|
19
|
+
# the relevant version if it is available.
|
20
|
+
# @return [Minimart::Mirror::SourceCookbook]
|
21
|
+
def find_cookbook(cookbook_name, version)
|
22
|
+
cookbooks.find do |cookbook|
|
23
|
+
cookbook.name == cookbook_name && cookbook.version == version
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Query this source for it's available cookbooks using the '/universe' endpoint.
|
28
|
+
# @return [Array<Minimart::Mirror::SourceCookbook]
|
29
|
+
def cookbooks
|
30
|
+
@cookbooks ||= fetch_universe_data.each_with_object([]) do |cookbook_info, memo|
|
31
|
+
name, versions = cookbook_info
|
32
|
+
memo.concat versions.map { |version, attrs| build_cookbook(name, version, attrs) }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_s
|
37
|
+
base_url
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def build_cookbook(name, version, attrs)
|
43
|
+
attrs = attrs.merge(name: name, version: version)
|
44
|
+
SourceCookbook.new(attrs)
|
45
|
+
end
|
46
|
+
|
47
|
+
def fetch_universe_data
|
48
|
+
Configuration.output.puts "Fetching the universe for #{base_url} ..."
|
49
|
+
|
50
|
+
Utils::Http.get_json(base_url, 'universe')
|
51
|
+
|
52
|
+
rescue RestClient::ResourceNotFound
|
53
|
+
raise Error::UniverseNotFoundError.new "no universe found for #{base_url}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'minimart/download/cookbook'
|
2
|
+
|
3
|
+
module Minimart
|
4
|
+
module Mirror
|
5
|
+
|
6
|
+
# A wrapper around a cookbook as found in the universe.json file from an
|
7
|
+
# external source (Chef Supermarket, etc...).
|
8
|
+
class SourceCookbook
|
9
|
+
|
10
|
+
# @return [String] the name of the cookbook
|
11
|
+
attr_accessor :name
|
12
|
+
|
13
|
+
# @return [String] the version of the cookbook
|
14
|
+
attr_accessor :version
|
15
|
+
|
16
|
+
# @return [Hash<String,String>] any dependencies the cookbook has
|
17
|
+
attr_accessor :dependencies
|
18
|
+
|
19
|
+
# @return [String] the path to the cookbook
|
20
|
+
attr_accessor :location_path
|
21
|
+
|
22
|
+
# @return [String] the type of location the cookbook is stored in (supermarket, etc.)
|
23
|
+
attr_accessor :location_type
|
24
|
+
|
25
|
+
# @return [String] URL to download the cookbook
|
26
|
+
attr_accessor :download_url
|
27
|
+
|
28
|
+
# @param [Hash] opts
|
29
|
+
# @option opts [String] name The name of the cookbook
|
30
|
+
# @option opts [String] version The version of the cookbook
|
31
|
+
# @option opts [String] location_path The path to the cookbook
|
32
|
+
# @option opts [String] download_url URL to download the cookbook
|
33
|
+
# @option opts [Hash] dependencies A hash containing any of the cookbook's dependencies.
|
34
|
+
# @option opts [String] location_type The type of location the cookbook is stored in (supermarket, etc.)
|
35
|
+
def initialize(opts)
|
36
|
+
@name = fetch_from_options(opts, 'name')
|
37
|
+
@version = fetch_from_options(opts, 'version')
|
38
|
+
@location_path = fetch_from_options(opts, 'location_path')
|
39
|
+
@download_url = fetch_from_options(opts, 'download_url')
|
40
|
+
@dependencies = fetch_from_options(opts, 'dependencies') || {}
|
41
|
+
@location_type = fetch_from_options(opts, 'location_type')
|
42
|
+
end
|
43
|
+
|
44
|
+
# Download this remote cookbook
|
45
|
+
# @yield [Dir] The path to the downloaded cookbook. This directory will be removed when the block exits.
|
46
|
+
def fetch(&block)
|
47
|
+
Download::Cookbook.new(self).fetch(&block)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Convert this remote cookbook to a Hash
|
51
|
+
# @return [Hash]
|
52
|
+
def to_hash
|
53
|
+
{
|
54
|
+
source_type: location_type,
|
55
|
+
location: location_path
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
# Get the location_path as a URI
|
60
|
+
# @return [URI]
|
61
|
+
def location_path_uri
|
62
|
+
URI.parse(location_path)
|
63
|
+
end
|
64
|
+
|
65
|
+
def web_friendly_version
|
66
|
+
version.gsub('.', '_')
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def fetch_from_options(opts, key)
|
72
|
+
opts[key] || opts[key.to_sym]
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Minimart
|
2
|
+
module Mirror
|
3
|
+
# A collection of Minimart::Mirror::Source
|
4
|
+
class Sources < Array
|
5
|
+
|
6
|
+
# @param [Array<String>] source_urls An array of source URL's specified in the inventory
|
7
|
+
def initialize(source_urls = [])
|
8
|
+
source_urls.each { |source_url| add_source(source_url) }
|
9
|
+
end
|
10
|
+
|
11
|
+
# Iterate over each cookbook defined in each source
|
12
|
+
# @yield [Minimart::Mirror::SourceCookbook]
|
13
|
+
def each_cookbook(&block)
|
14
|
+
each { |source| source.cookbooks.each(&block) }
|
15
|
+
end
|
16
|
+
|
17
|
+
# Find the first cookbook from the avaiable sources with a matching name, and
|
18
|
+
# version
|
19
|
+
# @param [String] name The name of the cookbook to search for
|
20
|
+
# @param [String] version The version of the cookbook to search for
|
21
|
+
def find_cookbook(name, version)
|
22
|
+
each do |source|
|
23
|
+
cookbook = source.find_cookbook(name, version)
|
24
|
+
return cookbook if cookbook
|
25
|
+
end
|
26
|
+
|
27
|
+
raise Error::CookbookNotFound, "The cookbook #{name} with the version #{version} could not be found"
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def add_source(source_url)
|
33
|
+
self << Source.new(source_url)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Minimart
|
2
|
+
# Wrapper for IO to provide colored output.
|
3
|
+
class Output
|
4
|
+
|
5
|
+
attr_reader :io
|
6
|
+
|
7
|
+
def initialize(io)
|
8
|
+
@io = io
|
9
|
+
end
|
10
|
+
|
11
|
+
def puts(*args)
|
12
|
+
io.puts(args)
|
13
|
+
end
|
14
|
+
|
15
|
+
def puts_red(str)
|
16
|
+
puts_color(31, str)
|
17
|
+
end
|
18
|
+
|
19
|
+
def puts_green(str)
|
20
|
+
puts_color(32, str)
|
21
|
+
end
|
22
|
+
|
23
|
+
def puts_yellow(str)
|
24
|
+
puts_color(33, str)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def puts_color(color_code, str)
|
30
|
+
self.puts "\e[#{color_code}m#{str}\e[0m"
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'archive/tar/minitar'
|
2
|
+
require 'zlib'
|
3
|
+
require 'minimart/mirror/download_metadata'
|
4
|
+
|
5
|
+
module Minimart
|
6
|
+
module Utils
|
7
|
+
|
8
|
+
# Archive manages tarring, and gzipping files
|
9
|
+
module Archive
|
10
|
+
|
11
|
+
# Extract a tar.gz archive
|
12
|
+
# @param [String] archive_file The path to the archive file
|
13
|
+
# @param [String] destination The directory to unpack the archive to
|
14
|
+
def self.extract_archive(archive_file, destination)
|
15
|
+
tar = Zlib::GzipReader.new(File.open(archive_file, 'rb'))
|
16
|
+
::Archive::Tar::Minitar.unpack(tar, destination)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Build a tar.tz archive from a directory
|
20
|
+
# @param [Minimart::Cookbook] cookbook The cookbook to archive
|
21
|
+
# @param [String] destination The path to store the tar.gz archive
|
22
|
+
def self.pack_archive(cookbook, destination)
|
23
|
+
Dir.mktmpdir do |tmp|
|
24
|
+
Dir.chdir(tmp) do
|
25
|
+
archive_dir = File.join(tmp, cookbook.name)
|
26
|
+
FileUtils.mkdir_p(archive_dir)
|
27
|
+
FileUtils.cp_r(File.join(cookbook.path, '.'), archive_dir)
|
28
|
+
meta_file = File.join(archive_dir, Minimart::Mirror::DownloadMetadata::FILE_NAME)
|
29
|
+
FileUtils.remove_entry(meta_file) if File.exists?(meta_file)
|
30
|
+
|
31
|
+
tgz = Zlib::GzipWriter.new(File.open(destination, 'wb'))
|
32
|
+
::Archive::Tar::Minitar.pack(cookbook.name, tgz)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Minimart
|
2
|
+
module Utils
|
3
|
+
# FileHelper contains helper methods for dealing with the file system.
|
4
|
+
module FileHelper
|
5
|
+
|
6
|
+
# Find the first cookbook in the given path
|
7
|
+
# @param [String] path The directory to search for cookbooks in
|
8
|
+
# @return [String] The path to the cookbook
|
9
|
+
def self.cookbook_path_in_directory(path)
|
10
|
+
cookbook_in_path?(path) ? path : find_cookbooks_in_directory(path).first
|
11
|
+
end
|
12
|
+
|
13
|
+
# List all of the cookbooks in a given directory
|
14
|
+
# @param [String] path The directory to find cookbooks in
|
15
|
+
# @return [Array<String>] An array of paths to any cookbooks found in the supplied path.
|
16
|
+
def self.find_cookbooks_in_directory(path)
|
17
|
+
Dir.glob(File.join(path, '/*/')).select { |d| cookbook_in_path?(d) }
|
18
|
+
end
|
19
|
+
|
20
|
+
# Determine whether or not a given directory contains a cookbook.
|
21
|
+
# @param [String] path The directory to check
|
22
|
+
# @return [Boolean]
|
23
|
+
def self.cookbook_in_path?(path)
|
24
|
+
file_exists?(File.join(path, 'metadata.json')) ||
|
25
|
+
file_exists?(File.join(path, 'metadata.rb'))
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.file_exists?(path)
|
29
|
+
File.exists?(path)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module Minimart
|
5
|
+
module Utils
|
6
|
+
# A collection of methods to help issue HTTP requests
|
7
|
+
module Http
|
8
|
+
|
9
|
+
# Issue a GET request to a URL, and return parsed JSON.
|
10
|
+
# @param [String] url The base URL to hit
|
11
|
+
# @param [String] path The path to the RESTful resource to fetch
|
12
|
+
# @return [Hash] The parsed JSON response
|
13
|
+
def self.get_json(url, path=nil)
|
14
|
+
JSON.parse(get(url, path, accept: 'application/json'))
|
15
|
+
end
|
16
|
+
|
17
|
+
# Issue a GET request to a URL
|
18
|
+
# @param [String] base_url The base URL to hit
|
19
|
+
# @param [String] path The path to the RESTful resource to fetch
|
20
|
+
def self.get(base_url, path=nil, headers={})
|
21
|
+
headers = headers.merge(verify_ssl: Minimart::Configuration.verify_ssl)
|
22
|
+
|
23
|
+
resource = RestClient::Resource.new(base_url.to_s)
|
24
|
+
path ? resource[path].get(headers) : resource.get(headers)
|
25
|
+
end
|
26
|
+
|
27
|
+
# GET a binary file
|
28
|
+
# @param [String] base_name A base name to give the returned file
|
29
|
+
# @param [String] url The base URL to hit
|
30
|
+
# @param [String] path The path to the RESTful resource to fetch
|
31
|
+
# @return [Tempfile]
|
32
|
+
def self.get_binary(base_name, url, path=nil)
|
33
|
+
result = Tempfile.new(base_name)
|
34
|
+
result.binmode
|
35
|
+
result.write(get(url, path))
|
36
|
+
result.close(false)
|
37
|
+
result
|
38
|
+
end
|
39
|
+
|
40
|
+
# Build a URL from a base URL, and a path
|
41
|
+
# @param [String] base_url The base URL to hit
|
42
|
+
# @param [String] path
|
43
|
+
def self.build_url(base_url, path=nil)
|
44
|
+
result = (base_url =~ /\A[a-z].*:\/\//i) ? base_url : "http://#{base_url}"
|
45
|
+
result = URI.parse(result).to_s
|
46
|
+
result = concat_url_fragment(result, path)
|
47
|
+
return result
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.concat_url_fragment(frag_one, frag_two)
|
51
|
+
return frag_one unless frag_two
|
52
|
+
result = frag_one
|
53
|
+
result << '/' unless result[-1] == '/'
|
54
|
+
result << ((frag_two[0] == '/') ? frag_two[1..-1] : frag_two)
|
55
|
+
result
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/minimart/web.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
module Minimart
|
2
|
+
# The Web namespace is used for building the cookbook index, and generating
|
3
|
+
# any HTML.
|
4
|
+
module Web
|
5
|
+
require 'minimart/web/cookbooks'
|
6
|
+
require 'minimart/web/html_generator'
|
7
|
+
require 'minimart/web/template_helper'
|
8
|
+
require 'minimart/web/universe_generator'
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Minimart
|
2
|
+
module Web
|
3
|
+
# Generate "show" pages for a set of cookbooks
|
4
|
+
class CookbookShowPageGenerator
|
5
|
+
include TemplateHelper
|
6
|
+
|
7
|
+
# @return [String] the directory to put any generated HTML in
|
8
|
+
attr_reader :web_directory
|
9
|
+
|
10
|
+
# @return [Minimart::Web::Cookbooks] the cookbooks to generate show pages for
|
11
|
+
attr_reader :cookbooks
|
12
|
+
|
13
|
+
# @param [Hash] opts
|
14
|
+
# @option opts [String] :web_directory The directory to put any generated HTML in
|
15
|
+
# @option opts [String] :cookbooks The cookbooks to generate show pages for
|
16
|
+
def initialize(opts = {})
|
17
|
+
@web_directory = opts[:web_directory]
|
18
|
+
@cookbooks = opts[:cookbooks]
|
19
|
+
end
|
20
|
+
|
21
|
+
# Generate the HTML!
|
22
|
+
def generate
|
23
|
+
clean_web_cookbooks_directory
|
24
|
+
make_web_cookbooks_directory
|
25
|
+
create_html_files
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def clean_web_cookbooks_directory
|
31
|
+
return unless Dir.exists?(cookbooks_directory)
|
32
|
+
FileUtils.remove_entry(cookbooks_directory)
|
33
|
+
end
|
34
|
+
|
35
|
+
def make_web_cookbooks_directory
|
36
|
+
FileUtils.mkdir_p(cookbooks_directory)
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_html_files
|
40
|
+
cookbooks.each do |cookbook_name, versions|
|
41
|
+
versions.each do |cookbook|
|
42
|
+
write_to_file(file(cookbook), template_content(cookbook, versions))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def file(cookbook)
|
48
|
+
FileUtils.mkdir_p(File.join(web_directory, cookbook_dir(cookbook)))
|
49
|
+
File.join(web_directory, cookbook_file(cookbook))
|
50
|
+
end
|
51
|
+
|
52
|
+
def template_content(cookbook, versions)
|
53
|
+
render_in_base_layout do
|
54
|
+
render_template('cookbook_show.erb', self, {cookbook: cookbook, other_versions: versions})
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def write_to_file(file_path, content)
|
59
|
+
File.open(file_path, 'w+') { |f| f.write(content) }
|
60
|
+
end
|
61
|
+
|
62
|
+
def cookbooks_directory
|
63
|
+
File.join(web_directory, 'cookbooks')
|
64
|
+
end
|
65
|
+
|
66
|
+
def cookbook_for_requirement(name, version_requirement)
|
67
|
+
(cookbooks[name] || []).find do |c|
|
68
|
+
c.satisfies_requirement?(version_requirement)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def level
|
73
|
+
2
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
require 'minimart/cookbook'
|
4
|
+
require 'minimart/utils/file_helper'
|
5
|
+
|
6
|
+
module Minimart
|
7
|
+
module Web
|
8
|
+
# Given a path to the inventory directory, this class will generate the necessary
|
9
|
+
# JSON output to power the main dashboard, and return cookbooks in a format
|
10
|
+
# that can be used to build the various web pages.
|
11
|
+
class Cookbooks
|
12
|
+
extend Forwardable
|
13
|
+
|
14
|
+
include Enumerable
|
15
|
+
|
16
|
+
FILE_NAME = 'data.json'
|
17
|
+
|
18
|
+
# @return [String] The path to the cookbook inventory
|
19
|
+
attr_reader :inventory_directory
|
20
|
+
|
21
|
+
# @param [Hash] opts
|
22
|
+
# @option opts [String] :inventory_directory The path to the cookbook inventory
|
23
|
+
def initialize(opts)
|
24
|
+
@inventory_directory = opts[:inventory_directory]
|
25
|
+
@data_structure = {}
|
26
|
+
|
27
|
+
generate
|
28
|
+
end
|
29
|
+
|
30
|
+
# Get a JSON representation of the most recent version of each cookbook
|
31
|
+
# found in the inventory_directory.
|
32
|
+
# @return [Hash]
|
33
|
+
def to_json
|
34
|
+
map do |cookbook_name, cookbook_versions|
|
35
|
+
cookbook_versions.first.to_hash.merge(available_versions: cookbook_versions.size)
|
36
|
+
end.to_json
|
37
|
+
end
|
38
|
+
|
39
|
+
def_delegators :data_structure, :each, :keys, :values, :[]
|
40
|
+
|
41
|
+
# Get a non-nested version of the cookbooks structure
|
42
|
+
def individual_cookbooks
|
43
|
+
values.flatten
|
44
|
+
end
|
45
|
+
|
46
|
+
# Add a cookbook to the data structure.
|
47
|
+
# @param [Minimart::Cookbook] cookbook The cookbook to add
|
48
|
+
def add(cookbook)
|
49
|
+
data_structure[cookbook.name] ||= []
|
50
|
+
data_structure[cookbook.name] << cookbook
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
attr_reader :data_structure
|
56
|
+
|
57
|
+
def generate
|
58
|
+
build_data_structure
|
59
|
+
sort_data
|
60
|
+
end
|
61
|
+
|
62
|
+
def build_data_structure
|
63
|
+
cookbooks.each { |cookbook| add(cookbook) }
|
64
|
+
end
|
65
|
+
|
66
|
+
# Sort cookbooks in version desc order
|
67
|
+
def sort_data
|
68
|
+
data_structure.values.map! do |versions|
|
69
|
+
versions.sort!.reverse!
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def cookbooks
|
74
|
+
inventory_cookbook_paths.map { |path| Minimart::Cookbook.from_path(path) }
|
75
|
+
end
|
76
|
+
|
77
|
+
def inventory_cookbook_paths
|
78
|
+
Utils::FileHelper.find_cookbooks_in_directory(inventory_directory)
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|