berktacular 0.1.1

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.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NzNiYWFhMGQ4YTY3ZTM5Zjg3Y2E1MDRjYjA2MWY2Yzg5OTk2MWIwNQ==
5
+ data.tar.gz: !binary |-
6
+ ZjI0MmRhODJmYmM1YWVmNjNiYjE4YTY5Y2EzMGVhNDQwNDkyODBjNg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ YjI2ZWIyZGFmZjgxYWY1ZDEzYjZlMDlmYzk4NjRkNDNiMTk1MTMzODc0ZDU2
10
+ NTgzODU1NmM1Y2JjNTk1ZmI3YTc4ODhkMThjNWQ0NWNjZmMxNDFkMDZhM2Qy
11
+ OTFkZGRmMzRmYTYzZTk4MWE3NDE1OWY0ODViYzdjYmQ3N2QyNDg=
12
+ data.tar.gz: !binary |-
13
+ ODcxYmUwODZlZjNkM2M0YjkxZmIwMDkxYTJhNmI0ZDMyYWUxM2VhYWI0ZDg3
14
+ YzcyNTcwMjBmOWEwYjAwY2VmY2Y5YzA4MmIyN2ViNjBiZTRkYTRlN2I1NWIw
15
+ MWQwNGE3YmMxZGVhMGUwNTRkZGExN2QzNzdkZmIyOTI2ZjA2MDQ=
data/bin/berktacular ADDED
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'fileutils'
5
+ require 'berktacular'
6
+
7
+ env_file = nil
8
+ check = false
9
+ upgrade = false
10
+ gtoken_path = File.join(ENV['HOME'], '.github-token')
11
+ github_token= nil
12
+ printit = false
13
+ berksfile = nil
14
+ new_envfile = nil
15
+ preserve = false
16
+ verify = nil
17
+ upload = false
18
+ berks_conf = nil
19
+ knife_conf = nil
20
+ workdir = nil
21
+ verbose = false
22
+
23
+ options = OptionParser.new do |opts|
24
+ opts.banner = "Read environment json file and spit out a berksfile"
25
+ opts.on("-e ENV.json", "--environment ENV.json", String, "Path to the environment file to use. Required.") do |f|
26
+ env_file = f
27
+ end
28
+ opts.on("-c", "--check", "Check for updates and print what they would be") do |c|
29
+ check = true
30
+ end
31
+ opts.on("-u", "--upgrade", "Auto-upgrade cookbooks that support it") do |u|
32
+ upgrade = true
33
+ end
34
+ opts.on("-p", "--print", "Print the berksfile to stdout") do |p|
35
+ printit = true
36
+ end
37
+ opts.on("-b PATH", "--berksfile PATH", String, "Write the berksfile to PATH.") do |b|
38
+ berksfile = b
39
+ end
40
+ opts.on("-n PATH", "--new-envfile PATH", String, "Write a new (updated) env file to PATH.") do |n|
41
+ new_envfile = n
42
+ end
43
+ opts.on("--[no-]verify", "Install cookbooks to WORKDIR and confirm that all dependancies are met") do |v|
44
+ verify = v
45
+ end
46
+ opts.on("--upload", "Upload the cookbooks and updated env file to the chef-server") do
47
+ upload = true
48
+ end
49
+ opts.on("--berksconfig BERKS_CONF", "The berkshelf config file to use. Defaults to ~/.chef/<env_name>-berkshelf.json") do |k|
50
+ berks_conf = k
51
+ end
52
+ opts.on("--knifeconfig KNIFE_CONF", "The knife config file to use. Defaults to ~/.chef/<env_name>-knife.rb") do |k|
53
+ knife_conf = k
54
+ end
55
+ opts.on("--github-token-file FILE", String, "Path to the github token to use") do |g|
56
+ gtoken_path = g
57
+ end
58
+ opts.on("-g TOKEN", "--github-token TOKEN", String, "The github token to use, not the path. This will show up in ps output") do |t|
59
+ github_token = t
60
+ end
61
+ opts.on("-w PATH","--workdir PATH", String, "The working directory to use, it will be created if need be.",
62
+ "The working directory is used to test the cookbook install.",
63
+ "Using this option prevents berktacular from deleting the workdir when done.",
64
+ "Using a tmpfs filesystem is recommended (used by default)",
65
+ "Default is a tmpdir somewhere (probably /tmp or /dev/shm)") do |w|
66
+ workdir = w
67
+ preserve = true
68
+ end
69
+ opts.on("-v", "--verbose", "Turn on verbose output" ) do
70
+ verbose = true
71
+ end
72
+ opts.on_tail("-h", "--help", "Print this help message" ) do
73
+ puts opts
74
+ exit 0
75
+ end
76
+ begin
77
+ opts.parse!
78
+ rescue OptionParser::ParseError, OptionParser::MissingArgument
79
+ warn opts
80
+ exit 1
81
+ end
82
+ end
83
+ # Enable verify by default if uploading, unless the user has surpressed it.
84
+ verify ||= upload
85
+
86
+ require 'json'
87
+ require 'solve'
88
+
89
+ unless env_file && File.exist?(env_file)
90
+ warn "No env file found at: '#{env_file}'"
91
+ warn options
92
+ exit 2
93
+ end
94
+
95
+ my_env = JSON.parse( File.read( env_file ) )
96
+
97
+ unless github_token
98
+ if File.exists? gtoken_path
99
+ github_token = IO.read(gtoken_path).strip
100
+ elsif upgrade || check
101
+ warn "No github token, cannot continue"
102
+ warn options
103
+ exit 3
104
+ end
105
+ end
106
+
107
+ if upload
108
+ berks_conf ||= "#{File.join(ENV['HOME'], File.basename(env_file, ".json") + "-berkshelf.json" )}"
109
+ unless File.exists? berks_conf
110
+ warn "The berkshelf config file could not be found at '#{berks_conf}'"
111
+ warn options
112
+ exit 4
113
+ end
114
+ knife_conf ||= "#{File.join(ENV['HOME'], File.basename(env_file, ".json") + "-knife.rb" )}"
115
+ unless File.exists? knife_conf
116
+ warn "The knife config file could not be found at '#{knife_conf}'"
117
+ warn options
118
+ exit 5
119
+ end
120
+ end
121
+
122
+ # Create a new berksfile
123
+ puts "Checking updates, this can take some time..." if check || upgrade
124
+ b = Berktacular::Berksfile.new(my_env, upgrade: upgrade, github_token: github_token, verbose: verbose)
125
+ b.check_updates if check
126
+ puts "#{b}" if printit
127
+ if berksfile
128
+ FileUtils.mkdir_p( File.dirname(berksfile) )
129
+ File.write(berksfile, b)
130
+ end
131
+ if new_envfile
132
+ FileUtils.mkdir_p( File.dirname(new_envfile))
133
+ File.write(new_envfile, JSON.pretty_generate(b.env_file))
134
+ end
135
+
136
+ if verify
137
+ unless b.verify(workdir)
138
+ puts "Berksfile verification failed"
139
+ b.missing_deps.each do |name, msg|
140
+ puts "#{name}\n\t#{msg}"
141
+ end
142
+ exit 10
143
+ end
144
+ puts "Berksfile Verified"
145
+ end
146
+
147
+ if upload
148
+ unless b.upload(knife_conf, workdir)
149
+ puts "Upload failed!"
150
+ exit 11
151
+ end
152
+ puts "Cookbooks and new environment file have been uploaded to the server"
153
+ end
154
+
155
+ b.clean unless preserve
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'fileutils'
4
+ require 'berktacular/version'
5
+
6
+ # This module contains classes that allow for generating Berksfiles from chef environment files.
7
+ module Berktacular
8
+
9
+ # @param h [Object] does a deep copy of whatever is passed in.
10
+ # @return [Object] a deep copy of the passed in object.
11
+ def self.deep_copy(h)
12
+ Marshal.load(Marshal.dump(h))
13
+ end
14
+
15
+ # @param [String] a command to run.
16
+ # @return [True] or raise on failure.
17
+ def self.run_command(cmd)
18
+ puts "Running command: #{cmd}"
19
+ unless system(cmd)
20
+ raise "Command failed with exit code #{$?.exitstatus}: #{cmd}"
21
+ end
22
+ end
23
+
24
+ # @return [String] the best tmpdir to use for this machine. Prefers /dev/shm if available.
25
+ def self.best_temp_dir
26
+ require 'tempfile'
27
+ tmp = if File.directory?("/dev/shm") && File.writable?("/dev/shm")
28
+ '/dev/shm'
29
+ else
30
+ '/tmp'
31
+ end
32
+ pat = [
33
+ Time.now().strftime('%Y_%m_%d-%H.%M.%S_'),
34
+ '_berktacular'
35
+ ]
36
+ Dir.mktmpdir(pat, tmp)
37
+ end
38
+
39
+ # Matches the numric version information from a tag.
40
+ VERSION_RE = Regexp.new(/\d+(?:\.\d+)*/)
41
+
42
+ autoload :Cookbook, 'berktacular/cookbook'
43
+ autoload :Berksfile, 'berktacular/berksfile'
44
+
45
+ end
@@ -0,0 +1,199 @@
1
+ module Berktacular
2
+
3
+ # This class represents a Berksfile
4
+
5
+ class Berksfile
6
+
7
+ # @!attribute [r] name
8
+ # @return [String] the name of the environment.
9
+ # @!attribute [r] description
10
+ # @return [String] a description of the enviroment.
11
+ # @!attribute [r] installed
12
+ # @return [Hash] a hash of installed cookbook directories.
13
+ # @!attribute [r] missing_deps
14
+ # @return [Hash] a hash of cookbooks missing dependencies after calling verify.
15
+ attr_reader :name, :description, :installed, :missing_deps
16
+
17
+ # Creates a new Berksfile from a chef environment file.
18
+ #
19
+ # @param environment [Hash] a parsed JSON chef environment config.
20
+ # @option opts [String] :github_token (nil) the github token to use.
21
+ # @option opts [True,False] :upgrade (False) whether or not to check for upgraded cookbooks.
22
+ # @option opts [True,False] :verbose (False) be more verbose.
23
+ def initialize( environment, opts = {})
24
+ @env_hash = environment # Save the whole thing so we can emit an updated version if needed.
25
+ @name = environment['name'] || nil
26
+ @description = environment['description'] || nil
27
+ @cookbook_versions = environment['cookbook_versions'] || {}
28
+ @cookbook_locations = environment['cookbook_locations'] || {}
29
+ @opts = {
30
+ :upgrade => opts.has_key?(:upgrade) ? opts[:upgrade] : false,
31
+ :github_token => opts.has_key?(:github_token) ? opts[:github_token] : nil,
32
+ :verbose => opts.has_key?(:verbose) ? opts[:verbose] : false
33
+ }
34
+ @installed = {}
35
+ # only connect once, pass the client to each cookbook. and only if needed
36
+ connect_to_git if @opts[:upgrade]
37
+ end
38
+
39
+ # @return [Hash] representation of the env_file.
40
+ def env_file
41
+ if @opts[:upgrade]
42
+ cookbooks.each do |book|
43
+ @env_hash['cookbook_versions'][book.name] = book.version_specifier
44
+ end
45
+ end
46
+ @env_hash
47
+ end
48
+
49
+ # @return [String] representation of the env_file in pretty json.
50
+ def env_file_json
51
+ if @opts[:upgrade]
52
+ cookbooks.each do |book|
53
+ @env_hash['cookbook_versions'][book.name] = book.version_specifier
54
+ end
55
+ end
56
+ JSON.pretty_generate(@env_hash)
57
+ end
58
+
59
+ # @param workdir [String] the directory in which to install. If nil, Berktacular.best_temp_dir is used.
60
+ # @return [String] the directory path where the cookbooks were installed.
61
+ def install(workdir = nil)
62
+ if workdir
63
+ FileUtils.mkdir_p(workdir)
64
+ else
65
+ workdir = Berktacular.best_temp_dir
66
+ end
67
+ unless @installed[workdir]
68
+ # remove the Berksfile.lock if it exists (it shouldn't).
69
+ berksfile = File.join(workdir, "Berksfile")
70
+ lck = berksfile + ".lock"
71
+ FileUtils.rm(lck) if File.exists? lck
72
+ File.write(berksfile, self)
73
+ Berktacular.run_command("berks install --berksfile #{berksfile} --path #{workdir}")
74
+ @installed[workdir] = {berksfile: berksfile, lck: lck}
75
+ end
76
+ workdir
77
+ end
78
+
79
+ # @params workdir [String] the directory in which to install. If nill, Berktacular.best_temp_dir is used.
80
+ # @return [True,False] the status of the verify.
81
+ def verify(workdir = nil)
82
+ require 'ridley'
83
+ @missing_deps = {}
84
+ workdir = install(workdir)
85
+ versions = {}
86
+ dependencies = {}
87
+ Dir["#{workdir}/*"].each do |cookbook_dir|
88
+ next unless File.directory?(cookbook_dir)
89
+ metadata_path = File.join(cookbook_dir, 'metadata.rb')
90
+ metadata = Ridley::Chef::Cookbook::Metadata.from_file(metadata_path)
91
+ cookbook_name = metadata.name
92
+ name_from_path = File.basename(cookbook_dir)
93
+ unless cookbook_name == name_from_path
94
+ if cookbook_name.empty?
95
+ puts "Cookbook #{name_from_path} has no name specified in metadata.rb"
96
+ cookbook_name = name_from_path
97
+ else
98
+ warn "Cookbook name from metadata.rb does not match the directory name!",
99
+ "metadata.rb: '#{cookbook_name}'",
100
+ "cookbook directory name: '#{name_from_path}'"
101
+ end
102
+ end
103
+ versions[cookbook_name] = metadata.version
104
+ dependencies[cookbook_name] = metadata.dependencies
105
+ end
106
+ errors = false
107
+ dependencies.each do |name, deps|
108
+ deps.each do |dep_name, constraint|
109
+ actual_version = versions[dep_name]
110
+ if !actual_version
111
+ @missing_deps[name] = "#{name}-#{versions[name]} depends on #{dep_name} which was not installed!"
112
+ warn @missing_deps[name]
113
+ errors = true
114
+ elsif !Solve::Constraint.new(constraint).satisfies?(actual_version)
115
+ @missing_deps[name] = "#{name}-#{versions[name]} depends on #{dep_name} #{constraint} but #{dep_name} is #{actual_version}!"
116
+ warn @missing_deps[name]
117
+ errors = true
118
+ end
119
+ end
120
+ end
121
+ !errors
122
+ end
123
+
124
+ # @param berks_conf [String] path to the berkshelf config file to use.
125
+ # @param knife_conf [String] path to the knife config file to use.
126
+ # @param workdir [String] Path to use as the working directory.
127
+ # @default Berktacular.best_temp_dir
128
+ # @return [True] or raise on error.
129
+ def upload(berks_conf, knife_conf, workdir=nil)
130
+ raise "No berks config, required for upload" unless berks_conf && File.exists?(berks_conf)
131
+ raise "No knife config, required for upload" unless knife_conf && File.exists?(knife_conf)
132
+ workdir = install(workdir)
133
+ new_env_file = File.write(File.join(workdir, @name + ".rb"), env_file_json )
134
+ Berktacular.run_command("berks upload --berksfile #{@installed[workdir][:berksfile]} --c #{berks_conf}")
135
+ Berktacular.run_command("knife environment from file #{new_env_file} -c #{knife_conf}")
136
+ end
137
+
138
+ # param workdir [String,nil] the workdir to remove. If nil, remove all installed working directories.
139
+ def clean(workdir = nil)
140
+ if workdir
141
+ Fileutils.rm_r(workdir)
142
+ @installed.delete(workdir)
143
+ else
144
+ # clean them all
145
+ @installed.keys.each { |d| FileUtils.rm_r(d) }
146
+ @installed = {}
147
+ end
148
+ end
149
+
150
+ # @param [IO] where to write the data.
151
+ def print_berksfile( io = STDOUT )
152
+ io.puts to_s
153
+ end
154
+
155
+ # @return [String] the berksfile as a String object
156
+ def to_s
157
+ str = ''
158
+ str << "# Name: '#{@name}'\n" if @name
159
+ str << "# Description: #{@description}\n\n" if @description
160
+ str << "# This file is auto-generated, changes will be overwritten\n"
161
+ str << "# Modify the .json environment file and regenerate this Berksfile to make changes.\n\n"
162
+
163
+ str << "site :opscode\n\n"
164
+ cookbooks.each { |l| str << l.to_s << "\n" }
165
+ str
166
+ end
167
+
168
+ # @return [Array] a list of Cookbook objects for this environment.
169
+ def cookbooks
170
+ @cookbooks ||= @cookbook_versions.sort.map do |book, version|
171
+ Cookbook.new(book, version, @cookbook_locations[book], @opts )
172
+ end
173
+ end
174
+
175
+ # print out the cookbooks that have newer version available on github.
176
+ def check_updates
177
+ connect_to_git
178
+ cookbooks.each do |b|
179
+ candidates = b.check_updates
180
+ next unless candidates.any?
181
+ puts "Cookbook: #{b.name} (auto upgrade: #{b.auto_upgrade ? 'enabled' : 'disabled'})",
182
+ "\tCurrent:#{b.version_number}",
183
+ "\tUpdates: #{candidates.join(", ")}"
184
+ end
185
+ end
186
+
187
+ private
188
+
189
+ # connect to github using the token in @opts[:github_token].
190
+ # @return [Octokit::Client] a connected github client.
191
+ def connect_to_git
192
+ raise "No token given, can't connect to git" unless @opts[:github_token]
193
+ puts "Connecting to git with supplied github_token" if @opts[:verbose]
194
+ require 'octokit'
195
+ @opts[:git_client] ||= Octokit::Client.new(access_token: @opts[:github_token])
196
+ end
197
+
198
+ end
199
+ end
@@ -0,0 +1,115 @@
1
+ module Berktacular
2
+
3
+ # This class represents a cookbook entry form a Berksfile
4
+
5
+ class Cookbook
6
+
7
+ # @!attribute [r] name
8
+ # @return [String] the name of the cookbook.
9
+ # @!attribute [r] version_number
10
+ # @return [String] the exact version of the cookbook.
11
+ # @!attribute [r] auto_upgrade
12
+ # @return [True, False] whether or now this cookbook can autoupgrade.
13
+ # @!attribute [r] config
14
+ # @return [Hash, nil] the cookbook_location hash associated with this cookbook or nil
15
+ attr_reader :name, :version_number, :auto_upgrade, :config
16
+
17
+ # Creates a new cookbook entry for a Berksfile.
18
+ #
19
+ # @param name [String] the name of the cookbook to use.
20
+ # @param version_spec [String] the exact version number as in a chef environment file. eg. '= 1.2.3'
21
+ # @param config [Hash,nil] the cookbook_location hash to for this cookbook. Optional.
22
+ # @option opts [Octokit::Client] :git_client (nil) the github client to use.
23
+ # @option opts [True,False] :upgrade (False) whether or not to check for updates. auto_upgrade must also be enbaled for the updated entry to be used.
24
+ # @option opts [True,False] :verbose (False) be more vervose.
25
+ def initialize( name, version_spec, config = nil, opts = {} )
26
+ @name = name || raise( "Missing cookbook name" )
27
+ @version_spec = version_spec || raise( "Missing cookbook version" )
28
+ @version_number = VERSION_RE.match( version_spec )[0]
29
+ @version_solved = Solve::Version.new(@version_number)
30
+ @auto_upgrade = config && config['auto_upgrade'] || false
31
+ @versions = config && config['versions'] || {}
32
+ @config = config ? config.reject{ |k,v| k == 'auto_upgrade' || k == 'versions' } : nil
33
+ @upgrade = opts.has_key?(:upgrade) ? opts[:upgrade] : false
34
+ @git_client = opts.has_key?(:git_client) ? opts[:git_client].dup : nil
35
+ @verbose = opts.has_key?(:verbose) ? opts[:verbose] : false
36
+ check_updates if @auto_upgrade && @upgrade
37
+ end
38
+
39
+ # @return [String] the exact version of the cookbook
40
+ def version_specifier
41
+ "= #{(@auto_upgrade && @upgrade && check_updates.any?) ? check_updates.first : @version_number }"
42
+ end
43
+
44
+ # @return [String] the latest available version number of the cookbook
45
+ def latest_version
46
+ check_updates.any? ? check_updates.first : @version_number
47
+ end
48
+
49
+ # @return [String] a Berksfile line for this cookbook
50
+ def to_s
51
+ line
52
+ end
53
+
54
+ # param upgrade [True,False] ('@upgrade') whether or not to force the lastest version when @auto_update is enabled
55
+ # @return [String] a Berksfile line for this cookbook
56
+ def line(upgrade = @upgrade)
57
+ "cookbook \"#{@name}\", #{generate_conf_line(upgrade, @config )}"
58
+ end
59
+
60
+ # @return [Array] a list of available cookbook version newer then we started with, with most recent first
61
+ def check_updates
62
+ @candidates ||= if @config && @config['github']
63
+ get_tags_from_github
64
+ else
65
+ []
66
+ end.select do |tag|
67
+ next if @config.has_key?('rel') && ! /^#{@name}-[v\d]/.match(tag)
68
+ m = VERSION_RE.match(tag)
69
+ next unless m
70
+ v = m[0]
71
+ begin
72
+ t = Solve::Version.new(v)
73
+ rescue Solve::Errors::InvalidVersionFormat
74
+ next
75
+ end
76
+ t > @version_solved
77
+ end.sort.reverse
78
+ end
79
+
80
+ private
81
+
82
+ # @param upgrade [True,False] use updated cookbook version if @auto_update is also true.
83
+ # @param config [Hash] the cookbook_locations hash associated with this cookbook.
84
+ # @return [String] the config line for this cookbook, everything after the cookbook name.
85
+ def generate_conf_line(upgrade, config)
86
+ ver = (upgrade && @candidates && @candiates.first) || @version_number
87
+ line = []
88
+ if config
89
+ if config.has_key?('github')
90
+ line << "github: \"#{config['github']}\""
91
+ line << "rel: \"#{config['rel']}\"" if config.has_key?('rel')
92
+ line << 'protocol: :ssh'
93
+ end
94
+ if @versions.has_key?(ver)
95
+ line << "ref: \"#{@versions[ver]['ref']}\""
96
+ else
97
+ if !@config.has_key?('tag')
98
+ line << "tag: \"#{ver}\""
99
+ else
100
+ line << "tag: \"#{@config['tag']}\""
101
+ end
102
+ end
103
+ else
104
+ line << " \"#{ver}\""
105
+ end
106
+ line.join(", ").gsub('%{version}', ver)
107
+ end
108
+
109
+ # return [Array] a list of tags from the github repository of this cookbook.
110
+ def get_tags_from_github
111
+ @git_client.repo(@config['github']).rels[:tags].get.data.map { |obj| obj.name }
112
+ end
113
+
114
+ end
115
+ end
@@ -0,0 +1,4 @@
1
+ module Berktacular
2
+ # the gem version.
3
+ VERSION = '0.1.1'
4
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: berktacular
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Jeff Harvey-Smith
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: solve
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '0.8'
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 0.8.2
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '0.8'
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 0.8.2
33
+ - !ruby/object:Gem::Dependency
34
+ name: ridley
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ version: '1.5'
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: 1.5.3
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ~>
48
+ - !ruby/object:Gem::Version
49
+ version: '1.5'
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: 1.5.3
53
+ - !ruby/object:Gem::Dependency
54
+ name: octokit
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ~>
58
+ - !ruby/object:Gem::Version
59
+ version: '3.0'
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: 3.0.0
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '3.0'
70
+ - - ! '>='
71
+ - !ruby/object:Gem::Version
72
+ version: 3.0.0
73
+ description: Generates a Berksfile from JSON style Chef environment files. Also support
74
+ extension to environment file with 'cookbook_locations'. Verifies the Berksfile
75
+ is consistent (all dependencies met) and will upload updated cookbooks and env files
76
+ to a chef server.
77
+ email:
78
+ - jeff@clearstorydata.com
79
+ executables:
80
+ - berktacular
81
+ extensions: []
82
+ extra_rdoc_files: []
83
+ files:
84
+ - bin/berktacular
85
+ - lib/berktacular.rb
86
+ - lib/berktacular/berksfile.rb
87
+ - lib/berktacular/cookbook.rb
88
+ - lib/berktacular/version.rb
89
+ homepage: https://rubygems.org/gems/berktacular
90
+ licenses:
91
+ - Apache License, Version 2.0
92
+ metadata: {}
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: '1.9'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ! '>='
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubyforge_project:
109
+ rubygems_version: 2.2.2
110
+ signing_key:
111
+ specification_version: 4
112
+ summary: Parse chef env files, generates a Berksfile and verifies it.
113
+ test_files: []
114
+ has_rdoc: