puppet-itemize 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: df934c90b977a46344d8d447060b93bd4fa87487
4
+ data.tar.gz: 732ec69ca41de35db175ab77af2c59f5f287e3fd
5
+ SHA512:
6
+ metadata.gz: c21938a92b1987f1f0d7f0f5b5a8f57ed9e1a0e5072275206c3dfcf12274da5d9253a5e4979ef37e438ce7c72afe65c13d099e3c5a7b3eeed3707ddae0d3dd2f
7
+ data.tar.gz: 8f2f894d7f6d5130759f04e5c85305220b16b3eba7921d51b5ae6eeaf67c0d2435d1b417a59872beb6fa3a49f009efc88460214e0e1ccc93eebd707174d7c0d3
data/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "{}"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright {yyyy} {name of copyright owner}
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,191 @@
1
+ # Puppet Itemize
2
+
3
+ Count the number of types, classes, functions used in manifest(s)
4
+
5
+ Run this command with a space separated list of either manifest file paths, or
6
+ directories containing manifests. If omitted, it will default to inspecting all
7
+ manifests in the manifests directory, so you can just run this in the root of a
8
+ Puppet module and it will do the right thing.
9
+
10
+ ## Installation
11
+
12
+ Install as either a gem:
13
+
14
+ ```
15
+ $ gem install puppet-itemize
16
+ ```
17
+
18
+ Or as a Puppet module:
19
+
20
+ ```
21
+ $ puppet module install binford2k/puppet_itemize
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ Depending on how it's installed, there are two ways to run this. As the command
27
+ line tool, `puppet-itemize`, or as the Puppet subcommand, `puppet parser itemize`.
28
+ There are slight, but mostly insignificant differences in behaviour based on
29
+ which way you run it.
30
+
31
+ Basically, just invoke the tool with a list of manifest(s), or directories of
32
+ manifests, or just let it default to the `./manifests` directory.
33
+
34
+ If you'd like machine parsable outputs, then use the `--render-as` flag and
35
+ pass in a format of `json` or `yaml`.
36
+
37
+ ### Command-line examples:
38
+ Available when installed via either gem or Puppet module.
39
+
40
+ ```
41
+ $ puppet-itemize
42
+ $ puppet-itemize manifests
43
+ $ puppet-itemize manifests/init.pp
44
+ $ puppet-itemize manifests/init.pp manifests/example/path.pp
45
+ ```
46
+
47
+ ### Puppet subcommand examples:
48
+ Available only when installed via Puppet module.
49
+
50
+ ```
51
+ $ puppet parser itemize
52
+ $ puppet parser itemize manifests
53
+ $ puppet parser itemize manifests/init.pp
54
+ $ puppet parser itemize manifests/init.pp manifests/example/path.pp
55
+ ```
56
+
57
+ ### Example output:
58
+
59
+ Because this is static analysis prior to compilation, no variables can be
60
+ resolved. Because of that, when a class name is calculated dynamically, any
61
+ variable parts of the name will be represented as `<??>`. See an example of that
62
+ below in the class list as `apache::mod::<??>`.
63
+
64
+ ```
65
+ $ puppet parser itemize ~/Projects/puppetlabs-apache/manifests/
66
+ Warning: create_resources detected. Please update to use iteration instead.
67
+ Resource usage analysis:
68
+ =======================================
69
+ >> types:
70
+ concat | 3
71
+ concat::fragment | 49
72
+ file | 81
73
+ exec | 8
74
+ apache::mod | 134
75
+ apache::default_mods::load | 1
76
+ package | 11
77
+ user | 1
78
+ group | 1
79
+ portage::makeconf | 8
80
+ apache::vhost | 3
81
+ anchor | 1
82
+ apache::mpm | 8
83
+ file_line | 3
84
+ yumrepo | 1
85
+ apache::peruser::multiplexer | 1
86
+ apache::security::rule_link | 1
87
+ service | 1
88
+ apache::custom_config | 1
89
+
90
+ >> classes:
91
+ apache::mod::proxy_balancer | 1
92
+ apache::confd::no_accf | 1
93
+ apache::mod::<??> | 2
94
+ apache::mod::authn_core | 4
95
+ apache::mod::reqtimeout | 2
96
+ apache::mod::actions | 2
97
+ apache::mod::cache | 2
98
+ apache::mod::ext_filter | 1
99
+ apache::mod::mime | 6
100
+ apache::mod::mime_magic | 2
101
+ apache::mod::rewrite | 3
102
+ apache::mod::speling | 2
103
+ apache::mod::suexec | 2
104
+ apache::mod::version | 2
105
+ apache::mod::vhost_alias | 3
106
+ apache::mod::disk_cache | 1
107
+ apache::mod::headers | 2
108
+ apache::mod::info | 1
109
+ apache::mod::userdir | 1
110
+ apache::mod::filter | 5
111
+ apache::mod::cgi | 1
112
+ apache::mod::cgid | 1
113
+ apache::mod::alias | 2
114
+ apache::mod::authn_file | 1
115
+ apache::mod::autoindex | 1
116
+ apache::mod::dav | 2
117
+ apache::mod::dav_fs | 1
118
+ apache::mod::deflate | 1
119
+ apache::mod::dir | 2
120
+ apache::mod::negotiation | 1
121
+ apache::mod::setenvif | 2
122
+ apache::mod::authz_default | 1
123
+ apache::mod::authz_user | 1
124
+ apache::mod::fastcgi | 2
125
+ apache::service | 1
126
+ apache::default_mods | 2
127
+ apache::default_confd_files | 1
128
+ apache | 39
129
+ apache::mod::dbd | 1
130
+ apache::mod::ldap | 1
131
+ apache::dev | 1
132
+ apache::mod::prefork | 1
133
+ apache::mod::proxy | 4
134
+ apache::mod::proxy_http | 2
135
+ apache::params | 2
136
+ apache::mod::socache_shmcb | 1
137
+ apache::package | 1
138
+ apache::mod::php | 1
139
+ apache::mod::python | 1
140
+ apache::mod::ssl | 2
141
+ apache::mod::auth_kerb | 1
142
+ apache::mod::wsgi | 1
143
+ apache::mod::passenger | 3
144
+
145
+ >> functions:
146
+ versioncmp | 47
147
+ ensure_resource | 3
148
+ inline_template | 2
149
+ template | 94
150
+ fail | 58
151
+ validate_re | 20
152
+ validate_bool | 23
153
+ regsubst | 6
154
+ defined | 55
155
+ is_absolute_path | 1
156
+ validate_apache_log_level | 2
157
+ warning | 16
158
+ is_array | 9
159
+ concat | 2
160
+ validate_absolute_path | 2
161
+ pick | 11
162
+ validate_string | 4
163
+ validate_array | 4
164
+ downcase | 4
165
+ validate_hash | 7
166
+ is_string | 2
167
+ has_key | 4
168
+ is_bool | 1
169
+ split | 2
170
+ empty | 20
171
+ enclose_ipv6 | 1
172
+ suffix | 2
173
+ any2array | 2
174
+ is_hash | 5
175
+ merge | 1
176
+ create_resources | 1
177
+ ```
178
+
179
+ ## Limitations
180
+
181
+ This is super early in development and has not yet been battle tested.
182
+
183
+
184
+ ## Disclaimer
185
+
186
+ I take no liability for the use of this tool.
187
+
188
+ Contact
189
+ -------
190
+
191
+ binford2k@gmail.com
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
3
+
4
+ require 'optparse'
5
+ require 'puppet_x/binford2k/itemize'
6
+ require 'puppet_x/binford2k/itemize/cli'
7
+
8
+ options = {
9
+ :manifests => 'manifests',
10
+ :render => :human,
11
+ }
12
+ OptionParser.new do |opts|
13
+ opts.banner = "Usage: puppet-inspect [options] <paths>
14
+
15
+ Run this command with a space separated list of either manifest file paths, or
16
+ directories containing manifests. If omitted, it will default to inspecting all
17
+ manifests in the manifests directory, so you can just run this in the root of a
18
+ Puppet module and it will do the right thing.
19
+
20
+ "
21
+
22
+ opts.on('-r', '--render-as FORMAT', 'Render the output as human, json, or yaml') do |val|
23
+ val = val.downcase.to_sym
24
+ fail "Unknown output type (#{val})" unless [:human, :json, :yaml].include? val
25
+ options[:render] = val
26
+ end
27
+
28
+ opts.on('-v', '--verbose', 'Show verbose output') do
29
+ options[:verbose] = true
30
+ end
31
+
32
+ opts.on('-d', '--debug', 'Show debugging messages') do
33
+ options[:debug] = true
34
+ end
35
+
36
+ opts.on('--shell', 'Open a pry shell for debugging (must have Pry installed)') do
37
+ options[:shell] = true
38
+ end
39
+
40
+ opts.on('--version', 'Show version number') do
41
+ puts Puppet_X::Binford2k::Itemize::VERSION
42
+ exit
43
+ end
44
+
45
+ end.parse!
46
+ options[:manifests] = ARGV unless ARGV.empty?
47
+
48
+ if options[:shell]
49
+ require 'pry'
50
+ binding.pry
51
+ exit 0
52
+ end
53
+
54
+ Puppet_X::Binford2k::Itemize::Cli.new(options).render!
@@ -0,0 +1,49 @@
1
+ require 'puppet/face'
2
+ require 'puppet_x/binford2k/itemize'
3
+ require 'puppet_x/binford2k/itemize/cli'
4
+
5
+ Puppet::Face.define(:parser, '0.0.1') do
6
+ action :itemize do
7
+ summary "Count the number of types, classes, functions used in manifest(s)"
8
+ arguments "[<manifest>] [<manifest> ...]"
9
+ returns "Displays count in human readable, json, or yaml format."
10
+ description <<-'EOT'
11
+ Run this command with a space separated list of either manifest file paths, or
12
+ directories containing manifests. If omitted, it will default to inspecting all
13
+ manifests in the manifests directory, so you can just run this in the root of a
14
+ Puppet module and it will do the right thing.
15
+ EOT
16
+
17
+ option('--shell') do
18
+ summary 'Start a debugging shell (requires Pry).'
19
+ end
20
+
21
+ examples <<-'EOT'
22
+ $ puppet parser itemize
23
+ $ puppet parser itemize manifests
24
+ $ puppet parser itemize manifests/init.pp
25
+ $ puppet parser itemize manifests/init.pp manifests/example/path.pp
26
+ EOT
27
+
28
+ when_invoked do |*args|
29
+ options = args.pop
30
+ options[:manifests] = args.empty? ? 'manifests' : args
31
+ options[:verbose] = [:info, :debug].include? Puppet::Util::Log.level
32
+ options[:debug] = Puppet::Util::Log.level == :debug
33
+
34
+ if options[:shell]
35
+ require 'pry'
36
+ binding.pry
37
+ exit 0
38
+ end
39
+
40
+ Puppet_X::Binford2k::Itemize::Cli.new(options).run!
41
+ end
42
+
43
+ when_rendering :console do |results|
44
+ results.to_s
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,10 @@
1
+ module Puppet_X
2
+ module Binford2k
3
+ class Itemize
4
+ VERSION = '0.0.1'
5
+
6
+ require 'puppet_x/binford2k/itemize/parser'
7
+ require 'puppet_x/binford2k/itemize/runner'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,61 @@
1
+ class Puppet_X::Binford2k::Itemize::Cli
2
+ def initialize(options = {})
3
+ @options = options
4
+ end
5
+
6
+ def run!
7
+ runner = Puppet_X::Binford2k::Itemize::Runner.new(@options).run!
8
+ @results = runner.results
9
+ self
10
+ end
11
+
12
+ def render!
13
+ run!
14
+
15
+ case @options[:render]
16
+ when :human
17
+ puts to_s
18
+ when :json
19
+ puts to_json
20
+ when :yaml
21
+ puts to_yaml
22
+ else
23
+ raise "Invalid render type (#{@options[:render]})."
24
+ end
25
+ end
26
+
27
+ def to_s
28
+ name_width = 2
29
+ count_width = 2
30
+ @results.each do |kind, counts|
31
+ counts.each do |name, count|
32
+ name_width = [name_width, name.size].max
33
+ count_width = [count_width, count.to_s.size].max
34
+ end
35
+ end
36
+
37
+ output = "Resource usage analysis:\n"
38
+ output << '=' * (name_width + count_width + 8)
39
+ output << "\n"
40
+ @results.each do |kind, counts|
41
+ output << ">> #{kind}:\n"
42
+
43
+ counts.each do |name, count|
44
+ output << sprintf(" %#{name_width}s | %#{count_width}s\n", name, count)
45
+ end
46
+ output << "\n"
47
+ end
48
+ output
49
+ end
50
+
51
+ def to_json
52
+ require 'json'
53
+ JSON.pretty_generate(@results)
54
+ end
55
+
56
+ def to_yaml
57
+ require 'yaml'
58
+ @results.to_yaml
59
+ end
60
+
61
+ end
@@ -0,0 +1,104 @@
1
+ require 'puppet'
2
+ require 'puppet/parser'
3
+ require 'puppet/util/logging'
4
+
5
+ class Puppet_X::Binford2k::Itemize::Parser
6
+ attr_reader :results
7
+
8
+ def initialize(filename, options = {})
9
+ @@visitor ||= Puppet::Pops::Visitor.new(nil, "count", 0, 0)
10
+ @filename = filename
11
+ @options = options
12
+ @results = {
13
+ :types => {},
14
+ :classes => {},
15
+ :functions => {},
16
+ }
17
+ Puppet::Util::Log.newdestination(:console)
18
+ end
19
+
20
+ def record(kind, thing)
21
+ fail("Unknown kind #{kind}") unless @results.keys.include? kind
22
+
23
+ thing = thing.sub(/^::/, '')
24
+ @results[kind][thing] ||= 0
25
+ @results[kind][thing] += 1
26
+ end
27
+
28
+ def parse!
29
+ begin
30
+ parser = Puppet::Pops::Parser::EvaluatingParser.new
31
+ source = Puppet::FileSystem.read(@filename)
32
+ result = parser.parse_string(source, @filename)
33
+ compute(result)
34
+ rescue => e
35
+ Puppet.err "Parse error for #{@filename}."
36
+ Puppet.err e.message
37
+ Puppet.debug e.backtrace.join "\n"
38
+ end
39
+ self
40
+ end
41
+
42
+ # Start walking the tree and count each tracked token
43
+ def compute(target)
44
+ @path = []
45
+ count(target)
46
+ target._pcore_all_contents(@path) { |element| count(element) }
47
+ # Puppet 4.x version
48
+ # target.eAllContents.each {|m| abc(m) }
49
+ @results
50
+ end
51
+
52
+ def count(o)
53
+ @@visitor.visit_this_0(self, o)
54
+ end
55
+
56
+ def count_Object(o)
57
+ # nop
58
+ end
59
+
60
+ def count_ResourceExpression(o)
61
+ resource_name = o.type_name.value
62
+ case resource_name
63
+ when 'class'
64
+ # for classes declared as resource-style, we have to traverse back up the
65
+ # tree to see if this resource body was declared by a class resource.
66
+ o.bodies.each do |klass|
67
+ record(:classes, klass.title.value)
68
+ end
69
+ else
70
+ record(:types, resource_name)
71
+ end
72
+ end
73
+
74
+ def count_CallNamedFunctionExpression(o)
75
+ function_name = o.functor_expr.value
76
+ case function_name
77
+ when 'include'
78
+ o.arguments.each do |klass|
79
+ case klass
80
+ when Puppet::Pops::Model::ConcatenatedString
81
+ # Because this is pre-compilation, we cannot resolve variables. So just tag w/ a marker
82
+ # TODO: This should go somewhere else, but I'm not entirely sure where just now.
83
+ record(:classes, klass.segments.map {|t| t.value rescue nil }.join('<??>'))
84
+ else
85
+ record(:classes, klass.value)
86
+ end
87
+ end
88
+
89
+ when 'create_resources'
90
+ Puppet.warning 'create_resources detected. Please update to use iteration instead.'
91
+ record(:functions, function_name)
92
+ record(:types, o.arguments.first.value)
93
+
94
+ else
95
+ record(:functions, function_name)
96
+ end
97
+ end
98
+
99
+ def dump!
100
+ require 'json'
101
+ puts JSON.pretty_generate(@results)
102
+ end
103
+
104
+ end
@@ -0,0 +1,43 @@
1
+ class Puppet_X::Binford2k::Itemize::Runner
2
+ attr_reader :results
3
+ def initialize(options = {})
4
+ @paths = expand(Array(options[:manifests]))
5
+ @options = options
6
+ @results = {}
7
+ end
8
+
9
+ def expand(paths)
10
+ paths.map do |path|
11
+ path = File.expand_path(path)
12
+
13
+ if File.file? path
14
+ path
15
+ elsif File.directory? path
16
+ Dir.glob("#{path}/**/*.pp")
17
+ else
18
+ raise "Path '#{path}' doesn't appear to be a file or directory"
19
+ end
20
+ end.flatten
21
+ end
22
+
23
+ def run!
24
+ @paths.each do |path|
25
+ parser = Puppet_X::Binford2k::Itemize::Parser.new(path, @options).parse!
26
+ parser.results.each do |kind, counts|
27
+ @results[kind] ||= {}
28
+
29
+ counts.each do |name, count|
30
+ @results[kind][name] ||= 0
31
+ @results[kind][name] += count
32
+ end
33
+ end
34
+ end
35
+ self
36
+ end
37
+
38
+ def dump!
39
+ require 'json'
40
+ puts JSON.pretty_generate(@results)
41
+ end
42
+
43
+ end
@@ -0,0 +1,7 @@
1
+ module Puppet_X
2
+ module Binford2k
3
+ class Itemize
4
+ VERSION = '0.0.1'
5
+ end
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: puppet-itemize
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ben Ford
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-10-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: |2
28
+ Run this command with a space separated list of either manifest file paths, or
29
+ directories containing manifests. If omitted, it will default to inspecting all
30
+ manifests in the manifests directory, so you can just run this in the root of a
31
+ Puppet module and it will do the right thing.
32
+ email: ben.ford@puppet.com
33
+ executables:
34
+ - puppet-itemize
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - LICENSE
39
+ - README.md
40
+ - bin/puppet-itemize
41
+ - lib/puppet/face/parser/itemize.rb
42
+ - lib/puppet_x/binford2k/itemize.rb
43
+ - lib/puppet_x/binford2k/itemize/cli.rb
44
+ - lib/puppet_x/binford2k/itemize/parser.rb
45
+ - lib/puppet_x/binford2k/itemize/runner.rb
46
+ - lib/puppet_x/binford2k/itemize/version.rb
47
+ homepage: https://github.com/binford2k/puppet-itemize
48
+ licenses:
49
+ - Apache-2.0
50
+ metadata: {}
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubyforge_project:
67
+ rubygems_version: 2.6.10
68
+ signing_key:
69
+ specification_version: 4
70
+ summary: Count the number of types, classes, functions used in Puppet manifest(s).
71
+ test_files: []