anthill-librarian-puppet 3.0.0

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