berktacular 0.1.1

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