anthill-librarian-puppet 3.0.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.
@@ -0,0 +1,21 @@
1
+ require 'librarian/action/resolve'
2
+
3
+ module Librarian
4
+ module Puppet
5
+ module Action
6
+ class Resolve < Librarian::Action::Resolve
7
+ include Librarian::Puppet::Util
8
+
9
+ def run
10
+ super
11
+ manifests = environment.lock.manifests.select{ |m| m.name }
12
+ dupes = manifests.group_by{ |m| module_name(m.name) }.select { |k, v| v.size > 1 }
13
+ dupes.each do |k,v|
14
+ warn("Dependency on module '#{k}' is fullfilled by multiple modules and only one will be used: #{v.map{|m|m.name}}")
15
+ end
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,110 @@
1
+ require 'librarian/helpers'
2
+
3
+ require 'librarian/cli'
4
+ require 'librarian/puppet'
5
+ require 'librarian/puppet/action'
6
+
7
+ module Librarian
8
+ module Puppet
9
+ class Cli < Librarian::Cli
10
+ include Librarian::Puppet::Util
11
+
12
+ module Particularity
13
+ def root_module
14
+ Puppet
15
+ end
16
+ end
17
+
18
+ include Particularity
19
+ extend Particularity
20
+
21
+ source_root Pathname.new(__FILE__).dirname.join("templates")
22
+
23
+ def init
24
+ copy_file environment.specfile_name
25
+
26
+ if File.exists? ".gitignore"
27
+ gitignore = File.read('.gitignore').split("\n")
28
+ else
29
+ gitignore = []
30
+ end
31
+
32
+ gitignore << ".tmp/" unless gitignore.include? ".tmp/"
33
+ gitignore << "modules/" unless gitignore.include? "modules/"
34
+
35
+ File.open(".gitignore", 'w') do |f|
36
+ f.puts gitignore.join("\n")
37
+ end
38
+ end
39
+
40
+ desc "install", "Resolves and installs all of the dependencies you specify."
41
+ option "quiet", :type => :boolean, :default => false
42
+ option "verbose", :type => :boolean, :default => false
43
+ option "line-numbers", :type => :boolean, :default => false
44
+ option "clean", :type => :boolean, :default => false
45
+ option "strip-dot-git", :type => :boolean
46
+ option "path", :type => :string
47
+ option "destructive", :type => :boolean, :default => false
48
+ option "local", :type => :boolean, :default => false
49
+ option "use-v1-api", :type => :boolean, :default => true
50
+ option "use-short-cache-path", :type => :boolean, :default => false
51
+ def install
52
+
53
+ ensure!
54
+ clean! if options["clean"]
55
+ unless options["destructive"].nil?
56
+ environment.config_db.local['destructive'] = options['destructive'].to_s
57
+ end
58
+ if options.include?("strip-dot-git")
59
+ strip_dot_git_val = options["strip-dot-git"] ? "1" : nil
60
+ environment.config_db.local["install.strip-dot-git"] = strip_dot_git_val
61
+ end
62
+ if options.include?("path")
63
+ environment.config_db.local["path"] = options["path"]
64
+ end
65
+
66
+ environment.config_db.local['use-v1-api'] = options['use-v1-api'] ? '1' : nil
67
+ environment.config_db.local['mode'] = options['local'] ? 'local' : nil
68
+ environment.config_db.local['use-short-cache-path'] = options['use-short-cache-path'] ? '1' : nil
69
+
70
+ resolve!
71
+ debug { "Install: dependencies resolved"}
72
+ install!
73
+ end
74
+
75
+ # only used to replace / to - in the module names
76
+ def update(*names)
77
+ warn("Usage of module/name is deprecated, use module-name") if names.any? {|n| n.include?("/")}
78
+ super(*names.map{|n| normalize_name(n)})
79
+ end
80
+
81
+ desc "package", "Cache the puppet modules in vendor/puppet/cache."
82
+ option "quiet", :type => :boolean, :default => false
83
+ option "verbose", :type => :boolean, :default => false
84
+ option "line-numbers", :type => :boolean, :default => false
85
+ option "clean", :type => :boolean, :default => false
86
+ option "strip-dot-git", :type => :boolean
87
+ option "path", :type => :string
88
+ option "destructive", :type => :boolean, :default => false
89
+ def package
90
+ environment.vendor!
91
+ install
92
+ end
93
+
94
+ def version
95
+ say "librarian-puppet v#{Librarian::Puppet::VERSION}"
96
+ end
97
+
98
+ private
99
+
100
+ # override the actions to use our own
101
+
102
+ def install!(options = { })
103
+ Action::Install.new(environment, options).run
104
+ end
105
+ def resolve!(options = { })
106
+ Action::Resolve.new(environment, options).run
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,18 @@
1
+ module Librarian
2
+ module Puppet
3
+
4
+ class Dependency < Librarian::Dependency
5
+
6
+ include Librarian::Puppet::Util
7
+
8
+ def initialize(name, requirement, source)
9
+ # Issue #235 fail if forge source is not defined
10
+ raise Error, "forge entry is not defined in Puppetfile" if source.instance_of?(Array) && source.empty?
11
+
12
+ super(normalize_name(name), requirement, source)
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,92 @@
1
+ require 'librarian/dsl'
2
+ require 'librarian/dsl/target'
3
+ require 'librarian/puppet/source'
4
+ require 'librarian/puppet/dependency'
5
+
6
+ module Librarian
7
+ module Puppet
8
+ class Dsl < Librarian::Dsl
9
+
10
+ FORGE_URL = "https://forgeapi.puppetlabs.com"
11
+
12
+ dependency :mod
13
+
14
+ source :forge => Source::Forge
15
+ source :git => Source::Git
16
+ source :path => Source::Path
17
+ source :github_tarball => Source::GitHubTarball
18
+
19
+ def default_specfile
20
+ Proc.new do
21
+ forge FORGE_URL
22
+ metadata
23
+ end
24
+ end
25
+
26
+ def self.dependency_type
27
+ Librarian::Puppet::Dependency
28
+ end
29
+
30
+ def post_process_target(target)
31
+ # save the default forge defined
32
+ default_forge = target.sources.select {|s| s.is_a? Librarian::Puppet::Source::Forge}.first
33
+ Librarian::Puppet::Source::Forge.default = default_forge || Librarian::Puppet::Source::Forge.from_lock_options(environment, :remote => FORGE_URL)
34
+ end
35
+
36
+ def receiver(target)
37
+ Receiver.new(target)
38
+ end
39
+
40
+ class Receiver < Librarian::Dsl::Receiver
41
+ attr_reader :specfile, :working_path
42
+
43
+ # save the specfile and call librarian
44
+ def run(specfile = nil)
45
+ @working_path = specfile.kind_of?(Pathname) ? specfile.parent : Pathname.new(Dir.pwd)
46
+ @specfile = specfile
47
+ super
48
+ end
49
+
50
+ # implement the 'modulefile' syntax for Puppetfile
51
+ def modulefile
52
+ f = modulefile_path
53
+ raise Error, "Modulefile file does not exist: #{f}" unless File.exists?(f)
54
+ File.read(f).lines.each do |line|
55
+ regexp = /\s*dependency\s+('|")([^'"]+)\1\s*(?:,\s*('|")([^'"]+)\3)?/
56
+ regexp =~ line && mod($2, $4)
57
+ end
58
+ end
59
+
60
+ # implement the 'metadata' syntax for Puppetfile
61
+ def metadata
62
+ f = working_path.join('metadata.json')
63
+ unless File.exists?(f)
64
+ msg = "Metadata file does not exist: #{f}"
65
+ # try modulefile, in case we don't have a Puppetfile and we are using the default template
66
+ if File.exists?(modulefile_path)
67
+ modulefile
68
+ return
69
+ else
70
+ raise Error, msg
71
+ end
72
+ end
73
+ begin
74
+ json = JSON.parse(File.read(f))
75
+ rescue JSON::ParserError => e
76
+ raise Error, "Unable to parse json file #{f}: #{e}"
77
+ end
78
+ dependencyList = json['dependencies']
79
+ dependencyList.each do |d|
80
+ mod(d['name'], d['version_requirement'])
81
+ end
82
+ end
83
+
84
+ private
85
+
86
+ def modulefile_path
87
+ working_path.join('Modulefile')
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,66 @@
1
+ require "librarian/environment"
2
+ require "librarian/puppet/dsl"
3
+ require "librarian/puppet/source"
4
+ require "librarian/puppet/lockfile"
5
+
6
+ module Librarian
7
+ module Puppet
8
+ class Environment < Librarian::Environment
9
+
10
+ def adapter_name
11
+ "puppet"
12
+ end
13
+
14
+ def lockfile
15
+ Lockfile.new(self, lockfile_path)
16
+ end
17
+
18
+ def ephemeral_lockfile
19
+ Lockfile.new(self, nil)
20
+ end
21
+
22
+ def tmp_path
23
+ part = config_db["tmp"] || ".tmp"
24
+ project_path.join(part)
25
+ end
26
+
27
+ def install_path
28
+ part = config_db["path"] || "modules"
29
+ project_path.join(part)
30
+ end
31
+
32
+ def vendor_path
33
+ project_path.join('vendor/puppet')
34
+ end
35
+
36
+ def vendor_cache
37
+ vendor_path.join('cache')
38
+ end
39
+
40
+ def vendor_source
41
+ vendor_path.join('source')
42
+ end
43
+
44
+ def vendor!
45
+ vendor_cache.mkpath unless vendor_cache.exist?
46
+ vendor_source.mkpath unless vendor_source.exist?
47
+ end
48
+
49
+ def vendor?
50
+ vendor_path.exist?
51
+ end
52
+
53
+ def local?
54
+ config_db['mode'] == 'local'
55
+ end
56
+
57
+ def use_v1_api
58
+ config_db['use-v1-api']
59
+ end
60
+
61
+ def use_short_cache_path
62
+ config_db['use-short-cache-path']
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,9 @@
1
+ require 'librarian/puppet/environment'
2
+ require 'librarian/action/base'
3
+
4
+ module Librarian
5
+ module Puppet
6
+ extend self
7
+ extend Librarian
8
+ end
9
+ end
@@ -0,0 +1,39 @@
1
+ # Extend Lockfile to normalize module names from acme/mod to acme-mod
2
+ module Librarian
3
+ module Puppet
4
+ class Lockfile < Librarian::Lockfile
5
+
6
+ # Extend the parser to normalize module names in old .lock files, converting / to -
7
+ class Parser < Librarian::Lockfile::Parser
8
+
9
+ include Librarian::Puppet::Util
10
+
11
+ def extract_and_parse_sources(lines)
12
+ sources = super
13
+ sources.each do |source|
14
+ source[:manifests] = Hash[source[:manifests].map do |name,manifest|
15
+ [normalize_name(name), manifest]
16
+ end]
17
+ end
18
+ sources
19
+ end
20
+
21
+ def extract_and_parse_dependencies(lines, manifests_index)
22
+ # when looking up in manifests_index normalize the name beforehand
23
+ class << manifests_index
24
+ include Librarian::Puppet::Util
25
+ alias_method :old_lookup, :[]
26
+ define_method(:[]) { |k| self.old_lookup(normalize_name(k)) }
27
+ end
28
+ super(lines, manifests_index)
29
+ end
30
+
31
+ end
32
+
33
+ def load(string)
34
+ Parser.new(environment).parse(string)
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,4 @@
1
+ require 'librarian/puppet/source/path'
2
+ require 'librarian/puppet/source/git'
3
+ require 'librarian/puppet/source/forge'
4
+ require 'librarian/puppet/source/githubtarball'
@@ -0,0 +1,181 @@
1
+ require 'uri'
2
+ require 'librarian/puppet/util'
3
+ require 'librarian/puppet/source/forge/repo_v1'
4
+ require 'librarian/puppet/source/forge/repo_v3'
5
+
6
+ module Librarian
7
+ module Puppet
8
+ module Source
9
+ class Forge
10
+ include Librarian::Puppet::Util
11
+
12
+ class << self
13
+ LOCK_NAME = 'FORGE'
14
+
15
+ def default=(source)
16
+ @@default = source
17
+ end
18
+
19
+ def default
20
+ @@default
21
+ end
22
+
23
+ def lock_name
24
+ LOCK_NAME
25
+ end
26
+
27
+ def from_lock_options(environment, options)
28
+ new(environment, options[:remote], options.reject { |k, v| k == :remote })
29
+ end
30
+
31
+ def from_spec_args(environment, uri, options)
32
+ recognised_options = []
33
+ unrecognised_options = options.keys - recognised_options
34
+ unless unrecognised_options.empty?
35
+ raise Error, "unrecognised options: #{unrecognised_options.join(", ")}"
36
+ end
37
+
38
+ new(environment, uri, options)
39
+ end
40
+
41
+ def client_api_version()
42
+ version = 1
43
+ pe_version = Librarian::Puppet.puppet_version.match(/\(Puppet Enterprise (.+)\)/)
44
+
45
+ # Puppet 3.6.0+ uses api v3
46
+ if Librarian::Puppet::puppet_gem_version >= Gem::Version.create('3.6.0.a')
47
+ version = 3
48
+ # Puppet enterprise 3.2.0+ uses api v3
49
+ elsif pe_version and Gem::Version.create(pe_version[1].strip) >= Gem::Version.create('3.2.0')
50
+ version = 3
51
+ end
52
+ return version
53
+ end
54
+
55
+ end
56
+
57
+ attr_accessor :environment
58
+ private :environment=
59
+ attr_reader :uri
60
+
61
+ def initialize(environment, uri, options = {})
62
+ self.environment = environment
63
+
64
+ if uri =~ %r{^http(s)?://forge\.puppetlabs\.com}
65
+ uri = "https://forgeapi.puppetlabs.com"
66
+ warn { "Replacing Puppet Forge API URL to use v3 #{uri}. You should update your Puppetfile" }
67
+ end
68
+
69
+ @uri = URI::parse(uri)
70
+ @cache_path = nil
71
+ end
72
+
73
+ def to_s
74
+ clean_uri(uri).to_s
75
+ end
76
+
77
+ def ==(other)
78
+ other &&
79
+ self.class == other.class &&
80
+ self.uri == other.uri
81
+ end
82
+
83
+ alias :eql? :==
84
+
85
+ def hash
86
+ self.to_s.hash
87
+ end
88
+
89
+ def to_spec_args
90
+ [clean_uri(uri).to_s, {}]
91
+ end
92
+
93
+ def to_lock_options
94
+ {:remote => clean_uri(uri).to_s}
95
+ end
96
+
97
+ def pinned?
98
+ false
99
+ end
100
+
101
+ def unpin!
102
+ end
103
+
104
+ def install!(manifest)
105
+ manifest.source == self or raise ArgumentError
106
+
107
+ debug { "Installing #{manifest}" }
108
+
109
+ name = manifest.name
110
+ version = manifest.version
111
+ install_path = install_path(name)
112
+ repo = repo(name)
113
+
114
+ repo.install_version! version, install_path
115
+ end
116
+
117
+ def manifest(name, version, dependencies)
118
+ manifest = Manifest.new(self, name)
119
+ manifest.version = version
120
+ manifest.dependencies = dependencies
121
+ manifest
122
+ end
123
+
124
+ def cache_path
125
+ @cache_path ||= begin
126
+ if environment.use_short_cache_path
127
+ # To shorten the cache path to avoid #17
128
+ # take only the first 7 digits of the SHA1 checksum of the forge URI
129
+ # (short Git commit hash approach)
130
+ dir = Digest::SHA1.hexdigest("#{uri.host}#{uri.path}")[0..6]
131
+ else
132
+ dir = "#{uri.host}#{uri.path}".gsub(/[^0-9a-z\-_]/i, '_')
133
+ end
134
+ environment.cache_path.join("source/puppet/forge/#{dir}")
135
+ end
136
+ end
137
+
138
+ def install_path(name)
139
+ environment.install_path.join(module_name(name))
140
+ end
141
+
142
+ def fetch_version(name, version_uri)
143
+ versions = repo(name).versions
144
+ if versions.include? version_uri
145
+ version_uri
146
+ else
147
+ versions.first
148
+ end
149
+ end
150
+
151
+ def fetch_dependencies(name, version, version_uri)
152
+ repo(name).dependencies(version).map do |k, v|
153
+ v = Librarian::Dependency::Requirement.new(v).to_gem_requirement
154
+ Dependency.new(k, v, nil)
155
+ end
156
+ end
157
+
158
+ def manifests(name)
159
+ repo(name).manifests
160
+ end
161
+
162
+ private
163
+
164
+ def repo(name)
165
+ @repo ||= {}
166
+
167
+ unless @repo[name]
168
+ # If we are using the official Forge then use API v3, otherwise use the preferred api
169
+ # as defined by the CLI option use_v1_api
170
+ if uri.hostname =~ /\.puppetlabs\.com$/ || !environment.use_v1_api
171
+ @repo[name] = RepoV3.new(self, name)
172
+ else
173
+ @repo[name] = RepoV1.new(self, name)
174
+ end
175
+ end
176
+ @repo[name]
177
+ end
178
+ end
179
+ end
180
+ end
181
+ end