puppet-library 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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