puppet 2.7.8 → 2.7.9

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (98) hide show
  1. data/CHANGELOG +6 -0
  2. data/README_DEVELOPER.md +63 -0
  3. data/conf/redhat/puppet.spec +4 -1
  4. data/ext/puppetstoredconfigclean.rb +39 -27
  5. data/lib/puppet.rb +1 -1
  6. data/lib/puppet/application/agent.rb +33 -25
  7. data/lib/puppet/application/apply.rb +15 -1
  8. data/lib/puppet/application/module.rb +3 -0
  9. data/lib/puppet/defaults.rb +4 -0
  10. data/lib/puppet/face/module.rb +12 -0
  11. data/lib/puppet/face/module/build.rb +31 -0
  12. data/lib/puppet/face/module/changes.rb +38 -0
  13. data/lib/puppet/face/module/clean.rb +30 -0
  14. data/lib/puppet/face/module/generate.rb +40 -0
  15. data/lib/puppet/face/module/install.rb +83 -0
  16. data/lib/puppet/face/module/search.rb +66 -0
  17. data/lib/puppet/indirector/exec.rb +1 -1
  18. data/lib/puppet/module_tool.rb +97 -0
  19. data/lib/puppet/module_tool/applications.rb +12 -0
  20. data/lib/puppet/module_tool/applications/application.rb +83 -0
  21. data/lib/puppet/module_tool/applications/builder.rb +91 -0
  22. data/lib/puppet/module_tool/applications/checksummer.rb +47 -0
  23. data/lib/puppet/module_tool/applications/cleaner.rb +16 -0
  24. data/lib/puppet/module_tool/applications/generator.rb +141 -0
  25. data/lib/puppet/module_tool/applications/installer.rb +89 -0
  26. data/lib/puppet/module_tool/applications/searcher.rb +40 -0
  27. data/lib/puppet/module_tool/applications/unpacker.rb +70 -0
  28. data/lib/puppet/module_tool/cache.rb +56 -0
  29. data/lib/puppet/module_tool/checksums.rb +52 -0
  30. data/lib/puppet/module_tool/contents_description.rb +82 -0
  31. data/lib/puppet/module_tool/dependency.rb +24 -0
  32. data/lib/puppet/module_tool/metadata.rb +141 -0
  33. data/lib/puppet/module_tool/modulefile.rb +75 -0
  34. data/lib/puppet/module_tool/repository.rb +79 -0
  35. data/lib/puppet/module_tool/skeleton.rb +34 -0
  36. data/lib/puppet/module_tool/skeleton/templates/generator/Modulefile.erb +11 -0
  37. data/lib/puppet/module_tool/skeleton/templates/generator/README.erb +16 -0
  38. data/lib/puppet/module_tool/skeleton/templates/generator/manifests/init.pp.erb +41 -0
  39. data/lib/puppet/module_tool/skeleton/templates/generator/metadata.json +12 -0
  40. data/lib/puppet/module_tool/skeleton/templates/generator/spec/spec_helper.rb +17 -0
  41. data/lib/puppet/module_tool/skeleton/templates/generator/tests/init.pp.erb +11 -0
  42. data/lib/puppet/module_tool/utils.rb +5 -0
  43. data/lib/puppet/module_tool/utils/interrogation.rb +25 -0
  44. data/lib/puppet/network/http/api/v1.rb +2 -1
  45. data/lib/puppet/parser/functions/create_resources.rb +19 -4
  46. data/lib/puppet/rails.rb +1 -1
  47. data/lib/puppet/rails/database/schema.rb +1 -1
  48. data/lib/puppet/ssl/host.rb +16 -8
  49. data/lib/puppet/transaction.rb +1 -1
  50. data/lib/puppet/type/file.rb +7 -2
  51. data/lib/puppet/type/file/ctime.rb +1 -1
  52. data/lib/puppet/type/file/mtime.rb +1 -1
  53. data/lib/puppet/type/file/type.rb +1 -1
  54. data/lib/puppet/util/queue/stomp.rb +19 -6
  55. data/lib/puppet/util/zaml.rb +39 -5
  56. data/spec/fixtures/releases/jamtur01-apache/Modulefile +2 -0
  57. data/spec/fixtures/releases/jamtur01-apache/files/httpd +24 -0
  58. data/spec/fixtures/releases/jamtur01-apache/files/test.vhost +18 -0
  59. data/spec/fixtures/releases/jamtur01-apache/lib/puppet/provider/a2mod/debian.rb +21 -0
  60. data/spec/fixtures/releases/jamtur01-apache/lib/puppet/type/a2mod.rb +12 -0
  61. data/spec/fixtures/releases/jamtur01-apache/manifests/dev.pp +5 -0
  62. data/spec/fixtures/releases/jamtur01-apache/manifests/init.pp +34 -0
  63. data/spec/fixtures/releases/jamtur01-apache/manifests/params.pp +17 -0
  64. data/spec/fixtures/releases/jamtur01-apache/manifests/php.pp +5 -0
  65. data/spec/fixtures/releases/jamtur01-apache/manifests/ssl.pp +15 -0
  66. data/spec/fixtures/releases/jamtur01-apache/manifests/vhost.pp +15 -0
  67. data/spec/fixtures/releases/jamtur01-apache/metadata.json +1 -0
  68. data/spec/fixtures/releases/jamtur01-apache/templates/vhost-default.conf.erb +20 -0
  69. data/spec/fixtures/releases/jamtur01-apache/tests/apache.pp +1 -0
  70. data/spec/fixtures/releases/jamtur01-apache/tests/dev.pp +1 -0
  71. data/spec/fixtures/releases/jamtur01-apache/tests/init.pp +1 -0
  72. data/spec/fixtures/releases/jamtur01-apache/tests/php.pp +1 -0
  73. data/spec/fixtures/releases/jamtur01-apache/tests/ssl.pp +1 -0
  74. data/spec/fixtures/releases/jamtur01-apache/tests/vhost.pp +2 -0
  75. data/spec/integration/module_tool_spec.rb +477 -0
  76. data/spec/integration/util/windows/security_spec.rb +1 -1
  77. data/spec/unit/application/agent_spec.rb +26 -0
  78. data/spec/unit/application/apply_spec.rb +12 -1
  79. data/spec/unit/face/module/build_spec.rb +30 -0
  80. data/spec/unit/face/module/changes_spec.rb +30 -0
  81. data/spec/unit/face/module/clean_spec.rb +30 -0
  82. data/spec/unit/face/module/generate_spec.rb +30 -0
  83. data/spec/unit/face/module/install_spec.rb +75 -0
  84. data/spec/unit/face/module/search_spec.rb +40 -0
  85. data/spec/unit/face/module_spec.rb +3 -0
  86. data/spec/unit/file_bucket/dipper_spec.rb +1 -1
  87. data/spec/unit/module_tool/application_spec.rb +29 -0
  88. data/spec/unit/module_tool/metadata_spec.rb +11 -0
  89. data/spec/unit/module_tool/repository_spec.rb +52 -0
  90. data/spec/unit/module_tool_spec.rb +38 -0
  91. data/spec/unit/network/http/api/v1_spec.rb +4 -0
  92. data/spec/unit/parser/functions/create_resources_spec.rb +21 -4
  93. data/spec/unit/rails_spec.rb +89 -158
  94. data/spec/unit/ssl/host_spec.rb +10 -33
  95. data/spec/unit/type/file_spec.rb +30 -0
  96. data/spec/unit/util/queue/stomp_spec.rb +9 -4
  97. data/spec/unit/util/zaml_spec.rb +37 -0
  98. metadata +77 -11
@@ -0,0 +1,52 @@
1
+ require 'digest/md5'
2
+
3
+ module Puppet::Module::Tool
4
+
5
+ # = Checksums
6
+ #
7
+ # This class proides methods for generating checksums for data and adding
8
+ # them to +Metadata+.
9
+ class Checksums
10
+ include Enumerable
11
+
12
+ # Instantiate object with string +path+ to create checksums from.
13
+ def initialize(path)
14
+ @path = Pathname.new(path)
15
+ end
16
+
17
+ # Return checksum for the +Pathname+.
18
+ def checksum(pathname)
19
+ return Digest::MD5.hexdigest(pathname.read)
20
+ end
21
+
22
+ # Return checksums for object's +Pathname+, generate if it's needed.
23
+ # Result is a hash of path strings to checksum strings.
24
+ def data
25
+ unless @data
26
+ @data = {}
27
+ @path.find do |descendant|
28
+ if Puppet::Module::Tool.artifact?(descendant)
29
+ Find.prune
30
+ elsif descendant.file?
31
+ path = descendant.relative_path_from(@path)
32
+ @data[path.to_s] = checksum(descendant)
33
+ end
34
+ end
35
+ end
36
+ return @data
37
+ end
38
+
39
+ # TODO: Why?
40
+ def each(&block)
41
+ data.each(&block)
42
+ end
43
+
44
+ # Update +Metadata+'s checksums with this object's.
45
+ def annotate(metadata)
46
+ metadata.checksums.replace(data)
47
+ end
48
+
49
+ # TODO: Move the Checksummer#run checksum checking to here?
50
+
51
+ end
52
+ end
@@ -0,0 +1,82 @@
1
+ module Puppet::Module::Tool
2
+
3
+ # = ContentsDescription
4
+ #
5
+ # This class populates +Metadata+'s Puppet type information.
6
+ class ContentsDescription
7
+
8
+ # Instantiate object for string +module_path+.
9
+ def initialize(module_path)
10
+ @module_path = module_path
11
+ end
12
+
13
+ # Update +Metadata+'s Puppet type information.
14
+ def annotate(metadata)
15
+ metadata.types.replace data.clone
16
+ end
17
+
18
+ # Return types for this module. Result is an array of hashes, each of which
19
+ # describes a Puppet type. The type description hash structure is:
20
+ # * :name => Name of this Puppet type.
21
+ # * :doc => Documentation for this type.
22
+ # * :properties => Array of hashes representing the type's properties, each
23
+ # containing :name and :doc.
24
+ # * :parameters => Array of hashes representing the type's parameters, each
25
+ # containing :name and :doc.
26
+ # * :providers => Array of hashes representing the types providers, each
27
+ # containing :name and :doc.
28
+ # TODO Write a TypeDescription to encapsulate these structures and logic?
29
+ def data
30
+ unless @data
31
+ @data = []
32
+ type_names = []
33
+ for module_filename in Dir[File.join(@module_path, "lib/puppet/type/*.rb")]
34
+ require module_filename
35
+ type_name = File.basename(module_filename, ".rb")
36
+ type_names << type_name
37
+
38
+ for provider_filename in Dir[File.join(@module_path, "lib/puppet/provider/#{type_name}/*.rb")]
39
+ require provider_filename
40
+ end
41
+ end
42
+
43
+ type_names.each do |type_name|
44
+ if type = Puppet::Type.type(type_name.to_sym)
45
+ type_hash = {:name => type_name, :doc => type.doc}
46
+ type_hash[:properties] = attr_doc(type, :property)
47
+ type_hash[:parameters] = attr_doc(type, :param)
48
+ if type.providers.size > 0
49
+ type_hash[:providers] = provider_doc(type)
50
+ end
51
+ @data << type_hash
52
+ else
53
+ Puppet.warning "Could not find/load type: #{type_name}"
54
+ end
55
+ end
56
+ end
57
+ @data
58
+ end
59
+
60
+ # Return an array of hashes representing this +type+'s attrs of +kind+
61
+ # (e.g. :param or :property), each containing :name and :doc.
62
+ def attr_doc(type, kind)
63
+ [].tap do |attrs|
64
+ type.allattrs.each do |name|
65
+ if type.attrtype(name) == kind && name != :provider
66
+ attrs.push(:name => name, :doc => type.attrclass(name).doc)
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ # Return an array of hashes representing this +type+'s providers, each
73
+ # containing :name and :doc.
74
+ def provider_doc(type)
75
+ [].tap do |providers|
76
+ type.providers.sort_by{ |o| o.to_s }.each do |prov|
77
+ providers.push(:name => prov, :doc => type.provider(prov).doc)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,24 @@
1
+ module Puppet::Module::Tool
2
+
3
+ class Dependency
4
+
5
+ # Instantiates a new module dependency with a +full_module_name+ (e.g.
6
+ # "myuser-mymodule"), and optional +version_requirement+ (e.g. "0.0.1") and
7
+ # optional repository (a URL string).
8
+ def initialize(full_module_name, version_requirement = nil, repository = nil)
9
+ @full_module_name = full_module_name
10
+ # TODO: add error checking, the next line raises ArgumentError when +full_module_name+ is invalid
11
+ @username, @name = Puppet::Module::Tool.username_and_modname_from(full_module_name)
12
+ @version_requirement = version_requirement
13
+ @repository = repository ? Repository.new(repository) : nil
14
+ end
15
+
16
+ # Return PSON representation of this data.
17
+ def to_pson(*args)
18
+ result = { :name => @full_module_name }
19
+ result[:version_requirement] = @version_requirement if @version_requirement && ! @version_requirement.nil?
20
+ result[:repository] = @repository.to_s if @repository && ! @repository.nil?
21
+ result.to_pson(*args)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,141 @@
1
+ module Puppet::Module::Tool
2
+
3
+ # = Metadata
4
+ #
5
+ # This class provides a data structure representing a module's metadata.
6
+ # It provides some basic parsing, but other data is injected into it using
7
+ # +annotate+ methods in other classes.
8
+ class Metadata
9
+
10
+ # The full name of the module, which is a dash-separated combination of the
11
+ # +username+ and module +name+.
12
+ attr_reader :full_module_name
13
+
14
+ # The name of the user that owns this module.
15
+ attr_reader :username
16
+
17
+ # The name of this module. See also +full_module_name+.
18
+ attr_reader :name
19
+
20
+ # The version of this module.
21
+ attr_reader :version
22
+
23
+ # Instantiate from a hash, whose keys are setters in this class.
24
+ def initialize(settings={})
25
+ settings.each do |key, value|
26
+ send("#{key}=", value)
27
+ end
28
+ end
29
+
30
+ # Set the full name of this module, and from it, the +username+ and
31
+ # module +name+.
32
+ def full_module_name=(full_module_name)
33
+ @full_module_name = full_module_name
34
+ @username, @name = Puppet::Module::Tool::username_and_modname_from(full_module_name)
35
+ end
36
+
37
+ # Return an array of the module's Dependency objects.
38
+ def dependencies
39
+ return @dependencies ||= []
40
+ end
41
+
42
+ def author
43
+ @author || @username
44
+ end
45
+
46
+ def author=(author)
47
+ @author = author
48
+ end
49
+
50
+ def source
51
+ @source || 'UNKNOWN'
52
+ end
53
+
54
+ def source=(source)
55
+ @source = source
56
+ end
57
+
58
+ def license
59
+ @license || 'Apache License, Version 2.0'
60
+ end
61
+
62
+ def license=(license)
63
+ @license = license
64
+ end
65
+
66
+ def summary
67
+ @summary || 'UNKNOWN'
68
+ end
69
+
70
+ def summary=(summary)
71
+ @summary = summary
72
+ end
73
+
74
+ def description
75
+ @description || 'UNKNOWN'
76
+ end
77
+
78
+ def description=(description)
79
+ @description = description
80
+ end
81
+
82
+ def project_page
83
+ @project_page || 'UNKNOWN'
84
+ end
85
+
86
+ def project_page=(project_page)
87
+ @project_page = project_page
88
+ end
89
+
90
+ # Return an array of the module's Puppet types, each one is a hash
91
+ # containing :name and :doc.
92
+ def types
93
+ return @types ||= []
94
+ end
95
+
96
+ # Return module's file checksums.
97
+ def checksums
98
+ return @checksums ||= {}
99
+ end
100
+
101
+ # Return the dashed name of the module, which may either be the
102
+ # dash-separated combination of the +username+ and module +name+, or just
103
+ # the module +name+.
104
+ def dashed_name
105
+ return [@username, @name].compact.join('-')
106
+ end
107
+
108
+ # Return the release name, which is the combination of the +dashed_name+
109
+ # of the module and its +version+ number.
110
+ def release_name
111
+ return [dashed_name, @version].join('-')
112
+ end
113
+
114
+ # Set the version of this module, ensure a string like '0.1.0' see the
115
+ # Semantic Versions here: http://semver.org
116
+ def version=(version)
117
+ if SemVer.valid?(version)
118
+ @version = version
119
+ else
120
+ raise ArgumentError, "Invalid version format: #{@version} (Semantic Versions are acceptable: http://semver.org)"
121
+ end
122
+ end
123
+
124
+ # Return the PSON record representing this instance.
125
+ def to_pson(*args)
126
+ return {
127
+ :name => @full_module_name,
128
+ :version => @version,
129
+ :source => source,
130
+ :author => author,
131
+ :license => license,
132
+ :summary => summary,
133
+ :description => description,
134
+ :project_page => project_page,
135
+ :dependencies => dependencies,
136
+ :types => types,
137
+ :checksums => checksums
138
+ }.to_pson(*args)
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,75 @@
1
+ module Puppet::Module::Tool
2
+
3
+ # = Modulefile
4
+ #
5
+ # This class provides the DSL used for evaluating the module's 'Modulefile'.
6
+ # These methods are used to concisely define this module's attributes, which
7
+ # are later rendered as PSON into a 'metadata.json' file.
8
+ class ModulefileReader
9
+
10
+ # Read the +filename+ and eval its Ruby code to set values in the Metadata
11
+ # +metadata+ instance.
12
+ def self.evaluate(metadata, filename)
13
+ returning(new(metadata)) do |builder|
14
+ if File.file?(filename)
15
+ builder.instance_eval(File.read(filename.to_s), filename.to_s, 1)
16
+ else
17
+ Puppet.warning "No Modulefile: #{filename}"
18
+ end
19
+ end
20
+ end
21
+
22
+ # Instantiate with the Metadata +metadata+ instance.
23
+ def initialize(metadata)
24
+ @metadata = metadata
25
+ end
26
+
27
+ # Set the +full_module_name+ (e.g. "myuser-mymodule"), which will also set the
28
+ # +username+ and module +name+. Required.
29
+ def name(name)
30
+ @metadata.full_module_name = name
31
+ end
32
+
33
+ # Set the module +version+ (e.g., "0.0.1"). Required.
34
+ def version(version)
35
+ @metadata.version = version
36
+ end
37
+
38
+ # Add a dependency with the full_module_name +name+ (e.g. "myuser-mymodule"), an
39
+ # optional +version_requirement+ (e.g. "0.0.1") and +repository+ (a URL
40
+ # string). Optional. Can be called multiple times to add many dependencies.
41
+ def dependency(name, version_requirement = nil, repository = nil)
42
+ @metadata.dependencies << Dependency.new(name, version_requirement, repository)
43
+ end
44
+
45
+ # Set the source
46
+ def source(source)
47
+ @metadata.source = source
48
+ end
49
+
50
+ # Set the author or default to +username+
51
+ def author(author)
52
+ @metadata.author = author
53
+ end
54
+
55
+ # Set the license
56
+ def license(license)
57
+ @metadata.license = license
58
+ end
59
+
60
+ # Set the summary
61
+ def summary(summary)
62
+ @metadata.summary = summary
63
+ end
64
+
65
+ # Set the description
66
+ def description(description)
67
+ @metadata.description = description
68
+ end
69
+
70
+ # Set the project page
71
+ def project_page(project_page)
72
+ @metadata.project_page = project_page
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,79 @@
1
+ require 'net/http'
2
+ require 'digest/sha1'
3
+ require 'uri'
4
+
5
+ module Puppet::Module::Tool
6
+
7
+ # = Repository
8
+ #
9
+ # This class is a file for accessing remote repositories with modules.
10
+ class Repository
11
+ include Utils::Interrogation
12
+
13
+ attr_reader :uri, :cache
14
+
15
+ # Instantiate a new repository instance rooted at the optional string
16
+ # +url+, else an instance of the default Puppet modules repository.
17
+ def initialize(url=Puppet[:module_repository])
18
+ @uri = url.is_a?(::URI) ? url : ::URI.parse(url)
19
+ @cache = Cache.new(self)
20
+ end
21
+
22
+ # Return a Net::HTTPResponse read for this +request+.
23
+ #
24
+ # Options:
25
+ # * :authenticate => Request authentication on the terminal. Defaults to false.
26
+ def make_http_request(request, options = {})
27
+ if options[:authenticate]
28
+ authenticate(request)
29
+ end
30
+ if ! @uri.user.nil? && ! @uri.password.nil?
31
+ request.basic_auth(@uri.user, @uri.password)
32
+ end
33
+ return read_response(request)
34
+ end
35
+
36
+ # Return a Net::HTTPResponse read from this HTTPRequest +request+.
37
+ def read_response(request)
38
+ begin
39
+ Net::HTTP::Proxy(
40
+ Puppet::Module::Tool::http_proxy_host,
41
+ Puppet::Module::Tool::http_proxy_port
42
+ ).start(@uri.host, @uri.port) do |http|
43
+ http.request(request)
44
+ end
45
+ rescue Errno::ECONNREFUSED, SocketError
46
+ raise RuntimeError, "Could not reach remote repository"
47
+ end
48
+ end
49
+
50
+ # Set the HTTP Basic Authentication parameters for the Net::HTTPRequest
51
+ # +request+ by asking the user for input on the console.
52
+ def authenticate(request)
53
+ Puppet.notice "Authenticating for #{@uri}"
54
+ email = prompt('Email Address')
55
+ password = prompt('Password', true)
56
+ request.basic_auth(email, password)
57
+ end
58
+
59
+ # Return the local file name containing the data downloaded from the
60
+ # repository at +release+ (e.g. "myuser-mymodule").
61
+ def retrieve(release)
62
+ return cache.retrieve(@uri + release)
63
+ end
64
+
65
+ # Return the URI string for this repository.
66
+ def to_s
67
+ return @uri.to_s
68
+ end
69
+
70
+ # Return the cache key for this repository, this a hashed string based on
71
+ # the URI.
72
+ def cache_key
73
+ return @cache_key ||= [
74
+ @uri.to_s.gsub(/[^[:alnum:]]+/, '_').sub(/_$/, ''),
75
+ Digest::SHA1.hexdigest(@uri.to_s)
76
+ ].join('-')
77
+ end
78
+ end
79
+ end