puppet-library 0.0.2 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 038f863a597766d136e7db4d8f71245844334d7c
4
- data.tar.gz: 0f98e71f5110f3875d4c03a401446bf400faa0bc
3
+ metadata.gz: dd852d5afc9f767f3adbd20e96a3d6ba37fec092
4
+ data.tar.gz: 9030ad628af928e81289963f28e9df751a4240b6
5
5
  SHA512:
6
- metadata.gz: 210fbe7f939854063796aacf44bcdd00da819f3ce97ede62ed58d00ad8c7cd787630aba645bbd460064a5f142da86613b65c920f7995bade1ded406fa049d6b6
7
- data.tar.gz: 4978484237188df4973d38aa8880dbfe3829d17753714f8f20cbb29bf85fbbb6426facb137fb71aefe4125e34dcf690142adf45747c5bffc869009abdb825458
6
+ metadata.gz: a168548b6050b5d34d121b1191f74dfe5a84e11024714f07d753828ef72894ef3b039ffbbd8c3c7a125179b29c4862ea8d4de17f2c45a3e0cf60527d48ae723a
7
+ data.tar.gz: 1c130b6732c99488fffc95442bca7b3604b0ae38213aba4415b185dd79514b705ee76cdc8710f1b53054f5428c54143b54ae80ec987c7a243888f51752602c5f
data/.travis.yml CHANGED
@@ -20,6 +20,5 @@ before_install:
20
20
  - gem --version
21
21
  rvm:
22
22
  - "1.8.7"
23
- - "1.9.2"
24
23
  - "1.9.3"
25
24
  - "2.0.0"
data/README.md CHANGED
@@ -1,11 +1,19 @@
1
1
  # Puppet Library
2
2
 
3
- A server for your Puppet modules. Compatible with [librarian-puppet](http://librarian-puppet.com).
3
+ A private server for your Puppet modules. Compatible with [librarian-puppet](http://librarian-puppet.com).
4
4
 
5
5
  [![Build Status](https://travis-ci.org/drrb/puppet-library.png?branch=master)](https://travis-ci.org/drrb/puppet-library)
6
6
  [![Coverage Status](https://coveralls.io/repos/drrb/puppet-library/badge.png)](https://coveralls.io/r/drrb/puppet-library)
7
+ [![Code Climate](https://codeclimate.com/github/drrb/puppet-library.png)](https://codeclimate.com/github/drrb/puppet-library)
7
8
 
8
- Puppet library serves packaged (`tar.gz`) modules from a directory of your choosing in the same format as [the Puppet Forge](http://forge.puppetlabs.com).
9
+ [![Gem Version](https://badge.fury.io/rb/puppet-library.png)](http://badge.fury.io/rb/puppet-library)
10
+ [![Dependency Status](https://gemnasium.com/drrb/puppet-library.png)](https://gemnasium.com/drrb/puppet-library)
11
+
12
+ Puppet Library serves Puppet modules in the same format as [the Puppet Forge](http://forge.puppetlabs.com). This allows you to create a private Puppet Forge and manage all the modules you use completely within your infrastructure.
13
+
14
+ Plugins can be created to serve modules from arbitrary sources. Puppet Library contains built-in support for:
15
+ - serving packaged (`.tar.gz`) modules from a directory (or directories) of your choosing
16
+ - proxying a remote forge (or forges)
9
17
 
10
18
  ## Installation
11
19
 
@@ -13,6 +21,12 @@ Install the server as a Gem:
13
21
 
14
22
  $ gem install puppet-library
15
23
 
24
+ Or, to get the latest, you can install from source
25
+
26
+ $ git clone https://github.com/drrb/puppet-library.git
27
+ $ cd puppet-library
28
+ $ rake install
29
+
16
30
  ## Getting Started
17
31
 
18
32
  Create a module directory and add the modules to it
@@ -24,7 +38,7 @@ Create a module directory and add the modules to it
24
38
 
25
39
  Start the server
26
40
 
27
- $ puppet-library
41
+ $ puppet-library --port 9292 --module-dir ./modules
28
42
 
29
43
  Point librarian-puppet to the server
30
44
 
@@ -40,7 +54,7 @@ Resolve and download the modules
40
54
 
41
55
  ## Usage
42
56
 
43
- Run the server
57
+ Run the server (proxies the Puppet Forge by default)
44
58
 
45
59
  $ puppet-library
46
60
 
@@ -48,6 +62,10 @@ Serve modules from a specific directory
48
62
 
49
63
  $ puppet-library --module-dir /var/puppet-modules
50
64
 
65
+ Serve modules from a remote forge as a proxy
66
+
67
+ $ puppet-library --proxy http://forge.puppetlabs.com
68
+
51
69
  Serve modules on a specific port
52
70
 
53
71
  $ puppet-library --port 8888
@@ -73,7 +91,7 @@ This project was inspired by [dalen/simple-puppet-forge](https://github.com/dale
73
91
  ## License
74
92
 
75
93
  Puppet Library
76
- Copyright (C) 2013 drrb
94
+ Copyright (C) 2014 drrb
77
95
 
78
96
  This program is free software: you can redistribute it and/or modify
79
97
  it under the terms of the GNU General Public License as published by
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  # Puppet Library
3
- # Copyright (C) 2013 drrb
3
+ # Copyright (C) 2014 drrb
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -19,14 +19,28 @@ require 'bundler/gem_tasks'
19
19
  require 'rspec/core/rake_task'
20
20
  require 'coveralls/rake/task'
21
21
 
22
- RSpec::Core::RakeTask.new(:spec)
22
+ if RUBY_VERSION.start_with? "1.8"
23
+ # The integration test doesn't work on Ruby 1.8.
24
+ DEFAULT_TEST_TASK = :spec
25
+ else
26
+ DEFAULT_TEST_TASK = :test
27
+ end
28
+
23
29
  Coveralls::RakeTask.new
24
30
 
25
- task :default => [:spec, 'coveralls:push']
31
+ desc "Run the specs"
32
+ RSpec::Core::RakeTask.new(:spec)
33
+
34
+ desc "Run all the tests"
35
+ RSpec::Core::RakeTask.new(:test) do |rspec|
36
+ rspec.pattern = "{spec,test}/**/*_{spec,integration_test}.rb"
37
+ end
38
+
39
+ task :default => [DEFAULT_TEST_TASK, 'coveralls:push']
26
40
 
27
41
  desc "Check it works on all local rubies"
28
42
  task :verify do
29
- system "rvm all do rake spec check-license"
43
+ system "rvm all do rake test"
30
44
  end
31
45
 
32
46
  desc "Check all files for license headers"
data/TODO.yml CHANGED
@@ -1,5 +1,16 @@
1
- Features:
2
- - Configure embedded server (currently uses the default Rack server)
3
- - Proxy another repository
1
+ features:
4
2
  - Use config from a config file
3
+ - Allow proxy to cache downloaded modules/API calls on disk
4
+ - |
5
+ Accept --cache-dir option to specify a parent cache directory (people
6
+ will need to embed the server or use a config file for more control)
7
+ - Validate repo dirs (make sure they're readable)
8
+ - Allow failover between module repositories
5
9
  - Document usage with Passenger
10
+ - Web UI
11
+ - Authentication
12
+
13
+ dubious_features:
14
+ - Make proxy cache TTL configurable
15
+ - REST API to clear proxy cache
16
+ - REST API to upload modules
data/config.ru CHANGED
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  # Puppet Library
3
- # Copyright (C) 2013 drrb
3
+ # Copyright (C) 2014 drrb
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -18,5 +18,9 @@
18
18
  require 'rubygems'
19
19
  require 'puppet_library'
20
20
 
21
- PuppetLibrary::Server.set :module_repo, ModuleRepo::Directory.new("/var/puppet-library/modules")
22
- run PuppetLibrary::Server
21
+ server = PuppetLibrary::Server.set_up do |library|
22
+ library.module_repo PuppetLibrary::ModuleRepo::Proxy.new("http://forge.puppetlabs.com")
23
+ library.module_repo PuppetLibrary::ModuleRepo::Directory.new("/var/lib/modules")
24
+ end
25
+
26
+ run server
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  # Puppet Library
3
- # Copyright (C) 2013 drrb
3
+ # Copyright (C) 2014 drrb
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -19,7 +19,11 @@ require 'puppet_library/version'
19
19
 
20
20
  require 'puppet_library/puppet_library'
21
21
  require 'puppet_library/server'
22
+ require 'puppet_library/http/cache'
23
+ require 'puppet_library/http/http_client'
24
+ require 'puppet_library/http/url'
22
25
  require 'puppet_library/module_metadata'
23
26
  require 'puppet_library/module_repo/directory'
24
27
  require 'puppet_library/module_repo/multi'
28
+ require 'puppet_library/module_repo/proxy'
25
29
  require 'puppet_library/util'
@@ -0,0 +1,100 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Puppet Library
3
+ # Copyright (C) 2014 drrb
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ class Array
19
+ def deep_merge
20
+ inject({}) do |merged, map|
21
+ merged.deep_merge(map)
22
+ end
23
+ end
24
+ end
25
+
26
+ class Hash
27
+ def deep_merge(other)
28
+ merge(other) do |key, old_val, new_val|
29
+ if old_val.instance_of? Array
30
+ old_val + new_val
31
+ else
32
+ new_val
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ module PuppetLibrary
39
+ class ModuleNotFound < Exception
40
+ end
41
+
42
+ class Forge
43
+ class Config
44
+ def initialize(module_repo)
45
+ @module_repo = module_repo
46
+ end
47
+
48
+ def module_repo(repo)
49
+ @module_repo.add_repo repo
50
+ end
51
+ end
52
+
53
+ def self.configure(&config_block)
54
+ module_repo = ModuleRepo::Multi.new
55
+ yield(Config.new(module_repo))
56
+ Forge.new(module_repo)
57
+ end
58
+
59
+ def initialize(module_repo)
60
+ @repo = module_repo
61
+ end
62
+
63
+ def get_module_metadata(author, name)
64
+ modules = get_metadata(author, name)
65
+
66
+ raise ModuleNotFound if modules.empty?
67
+
68
+ module_infos = modules.map { |m| m.to_info }
69
+ module_infos.deep_merge
70
+ end
71
+
72
+ def get_module_metadata_with_dependencies(author, name)
73
+ full_name = "#{author}/#{name}"
74
+
75
+ collect_dependencies_versions(full_name).tap do |versions|
76
+ raise ModuleNotFound if versions[full_name].empty?
77
+ end
78
+ end
79
+
80
+ def collect_dependencies_versions(module_full_name, metadata = {})
81
+ author, module_name = module_full_name.split "/"
82
+ module_versions = get_metadata(author, module_name)
83
+ metadata[module_full_name] = module_versions.map {|v| v.to_version }
84
+
85
+ dependencies = module_versions.map {|v| v.dependency_names }.flatten
86
+ dependencies.each do |dependency|
87
+ collect_dependencies_versions(dependency, metadata) unless metadata.include? dependency
88
+ end
89
+ return metadata
90
+ end
91
+
92
+ def get_module_buffer(author, name, version)
93
+ @repo.get_module(author, name, version) or raise ModuleNotFound
94
+ end
95
+
96
+ def get_metadata(author, module_name)
97
+ @repo.get_metadata(author, module_name).map {|metadata| ModuleMetadata.new(metadata)}
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,61 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Puppet Library
3
+ # Copyright (C) 2014 drrb
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ module PuppetLibrary::Http
19
+ class Cache
20
+ ARBITRARY_CACHE_TTL_MILLIS = 10 * 1000
21
+ def initialize(millis_to_live = ARBITRARY_CACHE_TTL_MILLIS)
22
+ @reaper = Reaper.new(millis_to_live)
23
+ @cache = {}
24
+ end
25
+
26
+ def get(key)
27
+ entry = @cache[key]
28
+ if entry
29
+ return entry.value unless @reaper.wants_to_kill? entry
30
+ end
31
+
32
+ value = yield
33
+ @cache[key] = Entry.new(value)
34
+ return value
35
+ end
36
+
37
+ class Entry
38
+ attr_accessor :value
39
+
40
+ def initialize(value)
41
+ @birth = Time.now
42
+ @value = value
43
+ end
44
+
45
+ def age_millis
46
+ age_seconds = Time.now - @birth
47
+ age_seconds * 1000
48
+ end
49
+ end
50
+
51
+ class Reaper
52
+ def initialize(millis_to_live)
53
+ @millis_to_live = millis_to_live
54
+ end
55
+
56
+ def wants_to_kill?(entry)
57
+ entry.age_millis > @millis_to_live
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,35 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Puppet Library
3
+ # Copyright (C) 2014 drrb
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'open-uri'
19
+
20
+ module PuppetLibrary::Http
21
+ class HttpClient
22
+ def get(url)
23
+ open_uri(url).read
24
+ end
25
+
26
+ def download(url)
27
+ open_uri(url)
28
+ end
29
+
30
+ private
31
+ def open_uri(url)
32
+ open(url)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Puppet Library
3
+ # Copyright (C) 2014 drrb
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ module PuppetLibrary::Http
19
+ class Url
20
+ def self.normalize(uri_string)
21
+ unless uri_string =~ /^https?/
22
+ uri_string = "http://#{uri_string}"
23
+ end
24
+ uri_string.sub /\/$/, ""
25
+ end
26
+ end
27
+ end
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  # Puppet Library
3
- # Copyright (C) 2013 drrb
3
+ # Copyright (C) 2014 drrb
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -17,7 +17,6 @@
17
17
 
18
18
  module PuppetLibrary
19
19
  class ModuleMetadata
20
-
21
20
  def initialize(metadata)
22
21
  @metadata = metadata
23
22
  end
@@ -42,6 +41,10 @@ module PuppetLibrary
42
41
  @metadata["dependencies"]
43
42
  end
44
43
 
44
+ def description
45
+ @metadata["description"]
46
+ end
47
+
45
48
  def dependency_names
46
49
  dependencies.map {|d| d["name"]}
47
50
  end
@@ -51,7 +54,7 @@ module PuppetLibrary
51
54
  "author" => author,
52
55
  "full_name" => full_name,
53
56
  "name" => name,
54
- "desc" => @metadata["description"],
57
+ "desc" => description,
55
58
  "releases" => [ { "version" => version } ]
56
59
  }
57
60
  end
@@ -60,7 +63,9 @@ module PuppetLibrary
60
63
  {
61
64
  "file" => "/modules/#{author}-#{name}-#{version}.tar.gz",
62
65
  "version" => version,
63
- "dependencies" => dependencies.map {|m| [ m["name"], m["version_requirement"] ]}
66
+ "dependencies" => dependencies.map do |dependency|
67
+ [ dependency["name"], dependency["version_requirement"] ]
68
+ end
64
69
  }
65
70
  end
66
71
  end