{"id":6537,"date":"2017-03-10T11:47:55","date_gmt":"2017-03-10T03:47:55","guid":{"rendered":"http:\/\/rmohan.com\/?p=6537"},"modified":"2017-03-10T11:48:29","modified_gmt":"2017-03-10T03:48:29","slug":"berkshelf","status":"publish","type":"post","link":"https:\/\/mohan.sg\/?p=6537","title":{"rendered":"BERKSHELF"},"content":{"rendered":"<div id=\"prod-versions\"><\/div>\n<h1 class=\"header\"><a href=\"http:\/\/berkshelf.com\/v2.0\/index.html\">BERKSHELF<\/a><\/h1>\n<p class=\"header\">Manage a Cookbook or an Application&#8217;s Cookbook dependencies<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>$ gem install berkshelf\r\nSuccessfully installed berkshelf-2.0.0\r\n1 gem installed\r\n<\/code><\/pre>\n<\/div>\n<p>Specify your dependencies in a Berksfile in your cookbook\u2019s root<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>site :opscode\r\n\r\ncookbook 'mysql'\r\ncookbook 'nginx', '~&gt; 0.101.5'\r\n<\/code><\/pre>\n<\/div>\n<p>Install the cookbooks you specified in the Berksfile and their dependencies<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>$ berks install\r\n<\/code><\/pre>\n<\/div>\n<p>Add the Berksfile to your project<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>$ git add Berksfile\r\n$ git commit -m \"add Berksfile to project\"\r\n<\/code><\/pre>\n<\/div>\n<blockquote><p>A Berksfile.lock will also be created. Add this to version control if you want to ensure that other developers (or your build server) will use the same versions of all cookbook dependencies.<\/p><\/blockquote>\n<h3 id=\"managing-an-existing-cookbook\">MANAGING AN EXISTING COOKBOOK<\/h3>\n<p>If you already have a cookbook and it\u2019s not managed by Berkshelf it\u2019s easy to get up and running. Just locate your cookbook and initialize it!<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>$ berks init ~\/code\/my_face-cookbook\r\n<\/code><\/pre>\n<\/div>\n<h3 id=\"creating-a-new-cookbook\">CREATING A NEW COOKBOOK<\/h3>\n<p>Want to start a new cookbook for a new application or supporting application?<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>$ berks cookbook new_application\r\n<\/code><\/pre>\n<\/div>\n<h2 id=\"getting-help\">GETTING HELP<\/h2>\n<p>If at anytime you are stuck or if you\u2019re just curious about what Berkshelf can do, just type the help command<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>$ berks help\r\n\r\nCommands:\r\n  berks apply ENVIRONMENT     # Apply the cookbook version locks from Berksfile.lock to a Chef environment\r\n  berks configure             # Create a new Berkshelf configuration file\r\n  berks contingent COOKBOOK   # List all cookbooks that depend on the given cookbook\r\n  berks cookbook NAME         # Create a skeleton for a new cookbook\r\n  berks help [COMMAND]        # Describe available commands or one specific command\r\n  berks init [PATH]           # Initialize Berkshelf in the given directory\r\n  berks install               # Install the cookbooks specified in the Berksfile\r\n  berks list                  # List all cookbooks (and dependencies) specified in the Berksfile\r\n  berks outdated [COOKBOOKS]  # Show outdated cookbooks (from the community site)\r\n  berks package [COOKBOOK]    # Package a cookbook (and dependencies) as a tarball\r\n  berks shelf SUBCOMMAND      # Interact with the cookbook store\r\n  berks show [COOKBOOK]       # Display name, author, copyright, and dependency information about a cookbook\r\n  berks update [COOKBOOKS]    # Update the cookbooks (and dependencies) specified in the Berksfile\r\n  berks upload [COOKBOOKS]    # Upload the cookbook specified in the Berksfile to the Chef Server\r\n  berks version               # Display version and copyright information\r\n\r\nOptions:\r\n  -c, [--config=PATH]    # Path to Berkshelf configuration to use.\r\n  -F, [--format=FORMAT]  # Output format to use.\r\n                         # Default: human\r\n  -q, [--quiet]          # Silence all informational output.\r\n  -d, [--debug]          # Output debug information\r\n<\/code><\/pre>\n<\/div>\n<p>You can get more detailed information about a command, or a sub command, but asking it for help<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>$ berks shelf help\r\n\r\nCommands:\r\n  berks shelf help [COMMAND]  # Describe subcommands or one specific subcommand\r\n  berks shelf list            # List all cookbooks and their versions\r\n  berks shelf show            # Display information about a cookbook in the Berkshelf shelf\r\n  berks shelf uninstall       # Remove a cookbook from the Berkshelf shelf\r\n<\/code><\/pre>\n<\/div>\n<h2 id=\"the-berkshelf\">THE BERKSHELF<\/h2>\n<blockquote><p>After running <code class=\"highlighter-rouge\">berks install<\/code> you may ask yourself, \u201cWhere did my cookbooks go?\u201d. They were added to The Berkshelf.<\/p><\/blockquote>\n<p>The Berkshelf is a location on your local disk which contains the cookbooks you have installed and their dependencies. By default, The Berkshelf is located at <code class=\"highlighter-rouge\">~\/.berkshelf<\/code> but this can be altered by setting the environment variable <code class=\"highlighter-rouge\">BERKSHELF_PATH<\/code>.<\/p>\n<p>Berkshelf stores every version of a cookbook that you have ever installed. This is the same pattern found with RubyGems where once you have resolved and installed a gem, you will have that gem and it\u2019s dependencies until you delete it.<\/p>\n<p>This central location is not the typical pattern of cookbook storage that you may be used to with Chef. The traditional pattern is to place all of your cookbooks in a directory called <code class=\"highlighter-rouge\">cookbooks<\/code> or <code class=\"highlighter-rouge\">site-cookbooks<\/code> within your <a href=\"http:\/\/wiki.opscode.com\/display\/chef\/Chef+Repository\">Chef Repository<\/a>. We do have all of our cookbooks in one central place, it\u2019s just not the Chef Repository and they\u2019re stored within directories named using the convention <code class=\"highlighter-rouge\"><span class=\"p\">{<\/span><span class=\"err\">name<\/span><span class=\"p\">}<\/span><span class=\"err\">-<\/span><span class=\"p\">{<\/span><span class=\"err\">version<\/span><span class=\"p\">}<\/span><\/code>.<\/p>\n<p>Given you have the cookbooks installed:<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>* nginx - 0.101.2\r\n* mysql - 1.2.4\r\n<\/code><\/pre>\n<\/div>\n<p>These cookbooks will be located at:<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>~\/.berkshelf\/cookbooks\/nginx-0.101.2\r\n~\/.berkshelf\/cookbooks\/mysql-1.2.4\r\n<\/code><\/pre>\n<\/div>\n<p>By default Chef interprets the name of a cookbook by the directory name. Some Chef internals weigh the name of the directory more heavily than if a cookbook developer were to explicitly set the <code class=\"highlighter-rouge\">name<\/code> attribute in their metadata. Because the directory structure contains the cookbook\u2019s version number, do not treat The Berkshelf as just another entry in your <code class=\"highlighter-rouge\">Chef::Config#cookbooks_path<\/code>.<\/p>\n<h3 id=\"vendoring-cookbooks\">VENDORING COOKBOOKS<\/h3>\n<p>You can easily install your Cookbooks and their dependencies to a location other than The Berkshelf. A good case for this is when you want to \u201cvendor\u201d your cookbooks to be packaged and distributed.<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>$ berks install --path vendor\/cookbooks\r\n<\/code><\/pre>\n<\/div>\n<p>This will install your Cookbooks to the <code class=\"highlighter-rouge\">vendor\/cookbooks<\/code> directory relative to where you ran the command from. Inside the vendored cookbooks directory you will find a directory named after the cookbook it contains.<\/p>\n<h2 id=\"configuring-berkshelf\">CONFIGURING BERKSHELF<\/h2>\n<p>Berkshelf will run with a default configuration unless you explicitly generate one. By default, Berkshelf uses the values found in your Knife configuration (if you have one).<\/p>\n<p>You can override this default behavior by generating an explicit Berkshelf configuration file with the <code class=\"highlighter-rouge\">configure<\/code> command<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>$ berks configure\r\n<\/code><\/pre>\n<\/div>\n<p>Answer each question prompt with a value or press enter to accept the default value. As with Berkshelf\u2019s default behavior, Berkshelf attempts to populate the default values from your Knife configuration (otherwise using something else sensible).<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>Config written to: '\/Users\/reset\/.berkshelf\/config.json'\r\n<\/code><\/pre>\n<\/div>\n<p>You will only be prompted to fill in the most travelled configuration options. Looking in the generated configuration will give you some insight to some other configurable values.<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code><span class=\"p\">{<\/span>\r\n  <span class=\"nt\">\"chef\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nt\">\"chef_server_url\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"https:\/\/api.opscode.com\/organizations\/vialstudios\"<\/span><span class=\"p\">,<\/span>\r\n    <span class=\"nt\">\"validation_client_name\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"chef-validator\"<\/span><span class=\"p\">,<\/span>\r\n    <span class=\"nt\">\"validation_key_path\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"\/etc\/chef\/validation.pem\"<\/span><span class=\"p\">,<\/span>\r\n    <span class=\"nt\">\"client_key\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"\/Users\/reset\/.chef\/reset.pem\"<\/span><span class=\"p\">,<\/span>\r\n    <span class=\"nt\">\"node_name\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"reset\"<\/span>\r\n  <span class=\"p\">},<\/span>\r\n  <span class=\"nt\">\"vagrant\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nt\">\"vm\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"nt\">\"box\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"Berkshelf-CentOS-6.3-x86_64-minimal\"<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"box_url\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"https:\/\/dl.dropbox.com\/u\/31081437\/Berkshelf-CentOS-6.3-x86_64-minimal.box\"<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"forward_port\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n\r\n      <span class=\"p\">},<\/span>\r\n      <span class=\"nt\">\"network\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n        <span class=\"nt\">\"bridged\"<\/span><span class=\"p\">:<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span>\r\n        <span class=\"nt\">\"hostonly\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"33.33.33.10\"<\/span>\r\n      <span class=\"p\">},<\/span>\r\n      <span class=\"nt\">\"provision\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"chef_solo\"<\/span>\r\n    <span class=\"p\">}<\/span>\r\n  <span class=\"p\">},<\/span>\r\n  <span class=\"nt\">\"ssl\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nt\">\"verify\"<\/span><span class=\"p\">:<\/span> <span class=\"kc\">true<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<\/div>\n<h3 id=\"configurable-options\">CONFIGURABLE OPTIONS<\/h3>\n<ul>\n<li><code class=\"highlighter-rouge\">chef.chef_server_url<\/code> &#8211; URL to a Chef Server API endpoint. (default: whatever is in your Knife file if you have one)<\/li>\n<li><code class=\"highlighter-rouge\">chef.node_name<\/code> &#8211; your Chef API client name. (default: whatever is in your Knife file if you have one)<\/li>\n<li><code class=\"highlighter-rouge\">chef.client_key<\/code> &#8211; filepath to your Chef API client key. (default: whatever is in your Knife file if you have one)<\/li>\n<li><code class=\"highlighter-rouge\">chef.validation_client_name<\/code> &#8211; your Chef API\u2019s validation client name. (default: whatever is in your Knife file if you have one)<\/li>\n<li><code class=\"highlighter-rouge\">chef.validation_key_path<\/code> &#8211; filepath to your Chef API\u2019s validation key. (default: whatever is in your Knife file if you have one)<\/li>\n<li><code class=\"highlighter-rouge\">vagrant.vm.box<\/code> &#8211; name of the VirtualBox box to use when provisioning Vagrant virtual machines. (default: Berkshelf-CentOS-6.3-x86_64-minimal)<\/li>\n<li><code class=\"highlighter-rouge\">vagrant.vm.box_url<\/code> &#8211; URL to the VirtualBox box (default: https:\/\/dl.dropbox.com\/u\/31081437\/Berkshelf-CentOS-6.3-x86_64-minimal.box)<\/li>\n<li><code class=\"highlighter-rouge\">vagrant.vm.forward_port<\/code> &#8211; a Hash of ports to forward where the key is the port to forward to on the guest and value is the host port which forwards to the guest on your host.<\/li>\n<li><code class=\"highlighter-rouge\">vagrant.vm.network.bridged<\/code> &#8211; use a bridged connection to connect to your virtual machine?<\/li>\n<li><code class=\"highlighter-rouge\">vagrant.vm.network.hostonly<\/code> &#8211; use a hostonly network for your virtual machine? (default: 33.33.33.10)<\/li>\n<li><code class=\"highlighter-rouge\">vagrant.vm.provision<\/code> &#8211; use the <code class=\"highlighter-rouge\">chef_solo<\/code> or <code class=\"highlighter-rouge\">chef_client<\/code> provisioner? (default: chef_solo)<\/li>\n<li><code class=\"highlighter-rouge\">ssl.verify<\/code> &#8211; should we verify all SSL http connections? (default: true)<\/li>\n<li><code class=\"highlighter-rouge\">cookbook.copyright<\/code> &#8211; the copyright information should be included when you generate new cookbooks. (default: whatever is in your Knife file if you have one)<\/li>\n<li><code class=\"highlighter-rouge\">cookbook.email<\/code> &#8211; the email address to include when you generate new cookbooks. (default: whatever is in your Knife file if you have one)<\/li>\n<li><code class=\"highlighter-rouge\">cookbook.license<\/code> &#8211; the license to use when you generate new cookbooks. (default: whatever is in your Knife file if you have one)<\/li>\n<\/ul>\n<blockquote><p>The configuration values are notated in \u2018dotted path\u2019 format. These translate to a nested JSON structure.<\/p><\/blockquote>\n<h2 id=\"vagrant-with-berkshelf\">VAGRANT WITH BERKSHELF<\/h2>\n<p>Berkshelf was designed for iterating on cookbooks and applications quickly. <a href=\"http:\/\/vagrantup.com\/\">Vagrant<\/a> provides us with a way to spin up a virtual environment and configure it using a built-in Chef provisioner. If you have never used Vagrant before &#8211; stop now &#8211; read the Vagrant documentation and give it a try. Your cookbook development life is about to become 100% better.<\/p>\n<p>If you have used Vagrant before, READ ON!<\/p>\n<h3 id=\"install-vagrant\">INSTALL VAGRANT<\/h3>\n<p>Visit the <a href=\"http:\/\/downloads.vagrantup.com\/\">Vagrant downloads page<\/a> and download the latest installer for your operating system.<\/p>\n<h3 id=\"install-the-vagrant-berkshelf-plugin\">INSTALL THE VAGRANT BERKSHELF PLUGIN<\/h3>\n<p>As of Berkshelf 1.3.0 there is now a separate gem which includes the <a href=\"https:\/\/github.com\/riotgames\/vagrant-berkshelf\">Vagrant Berkshelf plugin<\/a>. This plugin supports Vagrant 1.1.0 and greater.<\/p>\n<p>To install the plugin run the Vagrant plugin install command<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>$ vagrant plugin install vagrant-berkshelf\r\nInstalling the 'vagrant-berkshelf' plugin. This can take a few minutes...\r\nInstalled the plugin 'vagrant-berkshelf (1.2.0)!'\r\n<\/code><\/pre>\n<\/div>\n<h3 id=\"using-the-vagrant-berkshelf-plugin\">USING THE VAGRANT BERKSHELF PLUGIN<\/h3>\n<p>Once the Vagrant Berkshelf plugin is installed it can be enabled in your Vagrantfile<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>Vagrant.configure(\"2\") do |config|\r\n  ...\r\n  config.berkshelf.enabled = true\r\n  ...\r\nend\r\n<\/code><\/pre>\n<\/div>\n<blockquote><p>If your Vagrantfile was generated by Berkshelf it\u2019s probably already enabled<\/p><\/blockquote>\n<p>The plugin will look in your current working directory for your <code class=\"highlighter-rouge\">Berksfile<\/code> by default. Just ensure that your Berksfile exists and when you run <code class=\"highlighter-rouge\">vagrant up<\/code>, <code class=\"highlighter-rouge\">vagrant provision<\/code>, or <code class=\"highlighter-rouge\">vagrant destroy<\/code>the Berkshelf integration will automatically kick in!<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>$ vagrant provision\r\n[Berkshelf] Updating Vagrant's berkshelf: '\/Users\/reset\/.berkshelf\/vagrant\/berkshelf-20130320-28478-sy1k0n'\r\n[Berkshelf] Installing nginx (1.2.0)\r\n...\r\n<\/code><\/pre>\n<\/div>\n<p>You can use both the Vagrant provided Chef Solo and Chef Client provisioners with the Vagrant Berkshelf plugin.<\/p>\n<h4 id=\"chef-solo-provisioner\">Chef Solo provisioner<\/h4>\n<p>The Chef Solo provisioner\u2019s <code class=\"highlighter-rouge\">cookbook_path<\/code> attribute is hijacked when using the Vagrant Berkshelf plugin. Cookbooks resolved from your Berksfile will automatically be made available to your Vagrant virtual machine. There is no need to explicitly set a value for <code class=\"highlighter-rouge\">cookbook_path<\/code> attribute.<\/p>\n<h4 id=\"chef-client-provisioner\">Chef Client provisioner<\/h4>\n<p>Cookbooks will automatically be uploaded to the Chef Server you have configured in the Vagrantfile\u2019s Chef Client provisioner block. Your Berkshelf configuration\u2019s <code class=\"highlighter-rouge\">chef.node_name<\/code> and <code class=\"highlighter-rouge\">chef.client_key<\/code> credentials will be used to authenticate the upload.<\/p>\n<h4 id=\"setting-a-berksfile-location\">Setting a Berksfile location<\/h4>\n<p>By default, the Vagrant Berkshelf plugin will assume that the Vagrantfile is located in the same directory as a Berksfile. If your Berksfile is located in another directory you can override this behavior<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>Vagrant.configure(\"2\") do |config|\r\n  ...\r\n  config.berkshelf.berksfile_path = \"\/Users\/reset\/code\/my_face\/Berksfile\"\r\nend\r\n<\/code><\/pre>\n<\/div>\n<p>The above example will use an absolute path to the Berksfile of a sweet application called MyFace.<\/p>\n<h2 id=\"the-berksfile\">THE BERKSFILE<\/h2>\n<p>Dependencies are managed via the file <code class=\"highlighter-rouge\">Berksfile<\/code>. The Berksfile is like Bundler\u2019s Gemfile. Entries in the Berksfile are known as sources. It contains a list of sources identifying what Cookbooks to retrieve and where to get them.<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>metadata\r\ncookbook 'memcached'\r\ncookbook 'nginx'\r\ncookbook 'pvpnet', path: '\/Users\/reset\/code\/riot-cookbooks\/pvpnet-cookbook'\r\ncookbook 'mysql', git: 'git:\/\/github.com\/opscode-cookbooks\/mysql.git'\r\ncookbook 'myapp', chef_api: :config\r\n<\/code><\/pre>\n<\/div>\n<p>All sources <em>and<\/em> their dependencies will be retrieved, recursively. Two kinds of sources can be defined.<\/p>\n<h3 id=\"metadata-source\">METADATA SOURCE<\/h3>\n<p>The metadata source is like saying <code class=\"highlighter-rouge\">gemspec<\/code> in Bundler\u2019s <a href=\"http:\/\/gembundler.com\/man\/gemfile.5.html\">Gemfile<\/a>. It says, \u201cThere is a metadata.rb file within the same relative path of my Berksfile\u201d. This allows you to resolve a Cookbook\u2019s dependencies that you are currently working on just like you would resolve the dependencies of a Gem that you are currently working on with Bundler.<\/p>\n<p>Given a Berksfile at <code class=\"highlighter-rouge\">~\/code\/nginx-cookbook<\/code> containing:<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>metadata\r\n<\/code><\/pre>\n<\/div>\n<p>A <code class=\"highlighter-rouge\">metadata.rb<\/code> file is assumed to be located at <code class=\"highlighter-rouge\">~\/code\/nginx-cookbook\/metadata.rb<\/code>describing your nginx cookbook.<\/p>\n<h3 id=\"cookbook-source\">COOKBOOK SOURCE<\/h3>\n<p>A cookbook source is a way to describe a cookbook to install or a way to override the location of a dependency.<\/p>\n<p>Cookbook sources are defined with the format:<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>cookbook {name}, {version_constraint}, {options}\r\n<\/code><\/pre>\n<\/div>\n<p>The first parameter is the <code class=\"highlighter-rouge\">name<\/code> and is the only required parameter<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>cookbook \"nginx\"\r\n<\/code><\/pre>\n<\/div>\n<p>The second parameter is a <code class=\"highlighter-rouge\">version constraint<\/code> and is optional. If no version constraint is specified the latest is assumed<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>cookbook \"nginx\", \"&gt;= 0.101.2\"\r\n<\/code><\/pre>\n<\/div>\n<p>Constraints can be specified as<\/p>\n<ul>\n<li>Equal to (=)<\/li>\n<li>Greater than (&gt;)<\/li>\n<li>Greater than or equal to (&gt;=)<\/li>\n<li>Less than (&lt;)<\/li>\n<li>Less than or equal to (&lt;=)<\/li>\n<li>Pessimistic (~&gt;)<\/li>\n<\/ul>\n<p>The final parameter is an options hash<\/p>\n<h3 id=\"source-options\">SOURCE OPTIONS<\/h3>\n<p>Options passed to a source can contain a location or a group(s).<\/p>\n<h4 id=\"locations\">Locations<\/h4>\n<p>By default a cookbook source is assumed to come from the Opscode Community site <code class=\"highlighter-rouge\">http:\/\/cookbooks.opscode.com\/api\/v1\/cookbooks<\/code>. This behavior can be customized with a different location type. You might want to use a different location type if the cookbook is stored in a git repository, at a local file path, or at a different community site.<\/p>\n<h5 id=\"chef-api-location\">Chef API Location<\/h5>\n<p>The Chef API location allows you to treat your Chef Server like an <a href=\"http:\/\/en.wikipedia.org\/wiki\/Artifact_%28software_development%29\">artifact<\/a> server. Cookbooks or dependencies can be pulled directly out of a Chef Server. This is super useful if your organization has cookbooks that isn\u2019t available to the community but may be a dependency of other proprietary cookbooks in your organization.<\/p>\n<p>A Chef API Location is expressed with the <code class=\"highlighter-rouge\">chef_api<\/code> key followed by some options. You can tell Berkshelf to use the Chef credentials found in your Berkshelf config by passing the symbol <code class=\"highlighter-rouge\">:config<\/code> to <code class=\"highlighter-rouge\">chef_api<\/code>.<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>cookbook \"artifact\", chef_api: :config\r\n<\/code><\/pre>\n<\/div>\n<p>The Berkshelf configuration is by default located at <code class=\"highlighter-rouge\">~\/.berkshelf\/config.json<\/code>. You can specify a different configuration file with the <code class=\"highlighter-rouge\">-c<\/code> flag.<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>$ berks install -c \/Users\/reset\/.berkshelf\/production-config.json\r\n<\/code><\/pre>\n<\/div>\n<p>You can also explicitly define the <code class=\"highlighter-rouge\">chef_server_url<\/code>, <code class=\"highlighter-rouge\">node_name<\/code>, and <code class=\"highlighter-rouge\">client_key<\/code> to use:<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>cookbook \"artifact\", chef_api: \"https:\/\/api.opscode.com\/organizations\/vialstudios\", node_name: \"reset\", client_key: \"\/Users\/reset\/.chef\/reset.pem\"\r\n<\/code><\/pre>\n<\/div>\n<h5 id=\"site-location\">Site Location<\/h5>\n<p>The Site location can be used to specify a community site API to retrieve cookbooks from<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>cookbook \"artifact\", site: \"http:\/\/cookbooks.opscode.com\/api\/v1\/cookbooks\"\r\n<\/code><\/pre>\n<\/div>\n<p>The symbol <code class=\"highlighter-rouge\">:opscode<\/code> is an alias for \u201cOpscode\u2019s newest community API\u201d and can be provided in place of a URL<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>cookbook \"artifact\", site: :opscode\r\n<\/code><\/pre>\n<\/div>\n<h5 id=\"path-location\">Path Location<\/h5>\n<p>The Path location is useful for rapid iteration because it does not download, copy, or move the cookbook to The Berkshelf or change the contents of the target. Instead the cookbook found at the given filepath will be used alongside the cookbooks found in The Berkshelf.<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>cookbook \"artifact\", path: \"\/Users\/reset\/code\/artifact-cookbook\"\r\n<\/code><\/pre>\n<\/div>\n<p>The value given to <code class=\"highlighter-rouge\">:path<\/code> can only contain a single cookbook and <em>must<\/em> contain a <code class=\"highlighter-rouge\">metadata.rb<\/code> file.<\/p>\n<h5 id=\"git-location\">Git Location<\/h5>\n<p>The Git location will clone the given Git repository to The Berkshelf if the Git repository contains a valid cookbook.<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>cookbook \"mysql\", git: \"https:\/\/github.com\/opscode-cookbooks\/mysql.git\"\r\n<\/code><\/pre>\n<\/div>\n<p>Given the previous example, the cookbook found at the HEAD revision of the opscode-cookbooks\/mysql Github project will be cloned to The Berkshelf.<\/p>\n<p>An optional <code class=\"highlighter-rouge\">branch<\/code> key can be specified whose value is a branch or tag that contains the desired cookbook.<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>cookbook \"mysql\", git: \"https:\/\/github.com\/opscode-cookbooks\/mysql.git\", branch: \"foodcritic\"\r\n<\/code><\/pre>\n<\/div>\n<p>Given the previous example, the cookbook found at branch <code class=\"highlighter-rouge\">foodcritic<\/code> of the opscode-cookbooks\/mysql Github project will be cloned to The Berkshelf.<\/p>\n<p>An optional <code class=\"highlighter-rouge\">tag<\/code> key is an alias for <code class=\"highlighter-rouge\">branch<\/code> and can be used interchangeably.<\/p>\n<p>cookbook \u201cmysql\u201d, git: \u201chttps:\/\/github.com\/opscode-cookbooks\/mysql.git\u201d, tag: \u201c3.0.2\u201d<\/p>\n<p>Given the previous example, the cookbook found at tag <code class=\"highlighter-rouge\">3.0.2<\/code> of the opscode-cookbooks\/mysql Github project will be cloned to The Berkshelf.<\/p>\n<p>An optional <code class=\"highlighter-rouge\">ref<\/code> key can be specified for the exact SHA-1 commit ID to use and exact revision of the desired cookbook.<\/p>\n<p>cookbook \u201cmysql\u201d, git: \u201chttps:\/\/github.com\/opscode-cookbooks\/mysql.git\u201d, ref: \u201ceef7e65806e7ff3bdbe148e27c447ef4a8bc3881\u201d<\/p>\n<p>Given the previous example, the cookbook found at commit id <code class=\"highlighter-rouge\">eef7e65806e7ff3bdbe148e27c447ef4a8bc3881<\/code> of the opscode-cookbooks\/mysql Github project will be cloned to The Berkshelf.<\/p>\n<p>An optional <code class=\"highlighter-rouge\">rel<\/code> key can be specified if your repository contains many cookbooks in a single repository under a sub-directory or at root.<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>cookbook \"rightscale\", git: \"https:\/\/github.com\/rightscale\/rightscale_cookbooks.git\", rel: \"cookbooks\/rightscale\"\r\n<\/code><\/pre>\n<\/div>\n<p>This will fetch the cookbook <code class=\"highlighter-rouge\">rightscale<\/code> from the speficied Git location from under the <code class=\"highlighter-rouge\">cookbooks<\/code>sub-directory.<\/p>\n<h5 id=\"github-location\">GitHub Location<\/h5>\n<p>As of version 1.0.0, you may now use GitHub shorthand to specify a location.<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>cookbook \"artifact\", github: \"RiotGames\/artifact-cookbook\", tag: \"0.9.8\"\r\n<\/code><\/pre>\n<\/div>\n<p>Given this example, the <code class=\"highlighter-rouge\">artifact<\/code> cookbook from the <code class=\"highlighter-rouge\">RiotGames<\/code> organization in the <code class=\"highlighter-rouge\">artifact-cookbook<\/code> repository with a tag of <code class=\"highlighter-rouge\">0.9.8<\/code> will be cloned to The Berkshelf.<\/p>\n<p>The <code class=\"highlighter-rouge\">git<\/code> protocol will be used if no protocol is explicity set. To access a private repository specify the <code class=\"highlighter-rouge\">ssh<\/code> or <code class=\"highlighter-rouge\">https<\/code> protocol.<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>cookbook \"keeping_secrets\", github: \"RiotGames\/keeping_secrets-cookbook\", protocol: :ssh\r\n<\/code><\/pre>\n<\/div>\n<blockquote><p>You will receive a repository not found error if you are referencing a private repository and have not set the protocol to <code class=\"highlighter-rouge\">https<\/code> or <code class=\"highlighter-rouge\">ssh<\/code>.<\/p><\/blockquote>\n<h3 id=\"default-locations\">DEFAULT LOCATIONS<\/h3>\n<p>Any source that does not explicit define a location will attempted to be retrieved at the latest Opscode community API. Any source not explicitly defined in the Berksfile but found in the <code class=\"highlighter-rouge\">metadata.rb<\/code> of the current cookbook or a dependency will also attempt to use this default location.<\/p>\n<p>Additional site locations can be specified with the <code class=\"highlighter-rouge\">site<\/code> keyword in the Berksfile<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>site \"http:\/\/cookbooks.opscode.com\/api\/v1\/cookbooks\"\r\n<\/code><\/pre>\n<\/div>\n<p>This same entry could also have been written<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>site :opscode\r\n<\/code><\/pre>\n<\/div>\n<p>A Chef API default location can also be specified to attempt to retrieve your cookbook and it\u2019s dependencies from<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>chef_api \"https:\/\/api.opscode.com\/organizations\/vialstudios\", node_name: \"reset\", client_key: \"\/Users\/reset\/.chef\/reset.pem\"\r\n<\/code><\/pre>\n<\/div>\n<p>Provided my Berkshelf config contains these Chef credentials &#8211; this could have been simplified by using the <code class=\"highlighter-rouge\">:config<\/code> symbol<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>chef_api :config\r\n<\/code><\/pre>\n<\/div>\n<blockquote><p>Specifying a Chef API default location is particularly useful if you have cookbooks that are private to your organization that are not shared on the Opscode community site.<\/p>\n<p>It is highly recommended that you upload your cookbooks to your organization\u2019s Chef Server and then set a chef_api default location at the top of every application cookbook\u2019s Berksfile<\/p><\/blockquote>\n<h4 id=\"multiple-default-locations\">Multiple default locations<\/h4>\n<p>A combination of default locations can be specified in case a location is unavailable or does not contain the desired cookbook or version<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>chef_api :config\r\nsite :opscode\r\n\r\ncookbook \"artifact\", \"= 0.10.0\"\r\n<\/code><\/pre>\n<\/div>\n<p>The order in which the default locations keywords appear in the Berksfile is the order in which sources will be tried. In the above example Berkshelf would first try a Chef API using my Berkshelf configuration to find the \u201cartifact\u201d cookbook. If the Chef API didn\u2019t contain the \u201cartifact\u201d cookbook, or version 0.10.0 of the cookbook, it will try the Opscode community site.<\/p>\n<h3 id=\"groups\">GROUPS<\/h3>\n<p>Adding sources to a group is useful if you want to ignore a cookbook or a set of cookbooks at install or upload time.<\/p>\n<p>Groups can be defined via blocks:<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>group :solo do\r\n  cookbook 'riot_base'\r\nend\r\n<\/code><\/pre>\n<\/div>\n<p>Groups can also be defined inline as an option:<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>cookbook 'riot_base', group: 'solo'\r\n<\/code><\/pre>\n<\/div>\n<p>To exclude the groups when installing updating, or uploading just add the <code class=\"highlighter-rouge\">-except<\/code> flag.<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>$ berks install --except solo\r\n<\/code><\/pre>\n<\/div>\n<h2 id=\"generating-a-new-cookbook\">GENERATING A NEW COOKBOOK<\/h2>\n<p>Berkshelf includes a command to help you quickly generate a cookbook with a number of helpful supporting tools<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>$ berks cookbook my_face --foodcritic\r\n<\/code><\/pre>\n<\/div>\n<p>This will generate a cookbook called \u201cmy_face\u201d in your current directory with Vagrant, Git, and Foodcritic support. Check out <a href=\"http:\/\/vialstudios.com\/guide-authoring-cookbooks.html\">this guide<\/a> for more information and the help provided in the Berkshelf CLI for the cookbook command.<\/p>\n<h2 id=\"build-integration\">BUILD INTEGRATION<\/h2>\n<p>Instead of invoking Berkshelf directly on the command-line, you can also run Berkshelf from within a Thor process.<\/p>\n<h3 id=\"thor\">THOR<\/h3>\n<p>Just add the following line to your Thorfile:<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>require 'berkshelf\/thor'\r\n<\/code><\/pre>\n<\/div>\n<p>Now you have access to common Berkshelf tasks without shelling out<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>$ thor list\r\n\r\n$ berkshelf\r\n$ ---------\r\n$ thor berkshelf:init [PATH]  # Prepare a local path to have it's Cook...\r\n$ thor berkshelf:install      # Install the Cookbooks specified by a B...\r\n$ thor berkshelf:update       # Update all Cookbooks and their depende...\r\n$ thor berkshelf:upload       # Upload the Cookbooks specified by a Be...\r\n$ thor berkshelf:version      # Display version and copyright informat...\r\n\r\n\r\n\r\n<\/code><\/pre>\n<h2>Update your Gemfile<\/h2>\n<p>Update the Gemfile and dependencies; this is also in the development block because the CI will not need it:<\/p>\n<pre class=\"highlight\"><code><span class=\"n\">group<\/span> <span class=\"ss\">:development<\/span> <span class=\"k\">do<\/span>\r\n  <span class=\"n\">gem<\/span> <span class=\"s2\">\"knife-spork\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"1.0.17\"<\/span>\r\n  <span class=\"n\">gem<\/span> <span class=\"s2\">\"berkshelf\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"2.0.3\"<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<h2>Configure your Cookbook Dependencies<\/h2>\n<p>Create a new file <code>Berksfile<\/code> in the root of the project with the following content:<\/p>\n<pre class=\"highlight\"><code>site :opscode\r\n\r\ncookbook 'minitest-handler', '0.1.7'\r\n<\/code><\/pre>\n<p>This is like your Gem file for cookbooks.<\/p>\n<h2>Install the Community Cookbooks<\/h2>\n<p>Now, we want to install the cookbook dependency:<\/p>\n<pre class=\"highlight\"><code>bundle exec berks install\r\n<\/code><\/pre>\n<p>Before uploading our community cookbooks to the Chef server, we need to override one of the default configurations by creating a <code>config\/berks-config.json<\/code> file with the following content:<\/p>\n<pre class=\"highlight\"><code><span class=\"p\">{<\/span>\r\n  <span class=\"s2\">\"ssl\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"s2\">\"verify\"<\/span><span class=\"p\">:<\/span> <span class=\"kc\">false<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<p>When we upload the community cookbooks, Berkshelf will pull the settings from our <code>knife.rb<\/code> file and then the <code>berks-config.json<\/code> file. We could run this command to do so:<\/p>\n<pre class=\"highlight\"><code>bundle exec berks upload -c config\/berks-config.json\r\n<\/code><\/pre>\n<p>But, it makes sense to wrap this in a Rake task for usability:<\/p>\n<pre class=\"highlight\"><code><span class=\"n\">desc<\/span> <span class=\"s2\">\"Uploads Berkshelf cookbooks to our chef server\"<\/span>\r\n<span class=\"n\">task<\/span> <span class=\"ss\">:berks_upload<\/span> <span class=\"k\">do<\/span>\r\n  <span class=\"n\">sh<\/span> <span class=\"s2\">\"bundle exec berks upload -c config\/berks-config.json\"<\/span>\r\n<span class=\"k\">end<\/span>\r\n<\/code><\/pre>\n<h2>Update the Vagrant File Run List<\/h2>\n<p>Finally, we modify the run list for in our Vagrant file to support the mini test handler:<\/p>\n<pre class=\"highlight\"><code><span class=\"p\">.<\/span><span class=\"nf\">.<\/span><span class=\"p\">.<\/span>\r\n<span class=\"nf\">chef<\/span><span class=\"p\">.<\/span><span class=\"nf\">run_list<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span>\r\n    <span class=\"s1\">'motd'<\/span><span class=\"p\">,<\/span>\r\n    <span class=\"s1\">'minitest-handler'<\/span>\r\n<span class=\"p\">]<\/span>\r\n<span class=\"p\">.<\/span><span class=\"nf\">.<\/span><span class=\"o\">.<\/span>\r\n<\/code><\/pre>\n<p>Running a <code>vagrant provision<\/code> will now execute our MOTD cookbook, and then run a blank minitest suite against it.<\/p>\n<h2>Coming up\u2026<\/h2>\n<p>Next time, we will conclude our series by setting up final verification tests with a post on &#8220;Minitest&#8221; and make it part of our workflow process.<\/p>\n<pre class=\"highlight\"><code>\u00a0<\/code><\/pre>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p> BERKSHELF <\/p>\n<p class=\"header\">Manage a Cookbook or an Application&#8217;s Cookbook dependencies<\/p>\n<p> $ gem install berkshelf Successfully installed berkshelf-2.0.0 1 gem installed <\/p>\n<p>Specify your dependencies in a Berksfile in your cookbook\u2019s root<\/p>\n<p> site :opscode cookbook &#8216;mysql&#8217; cookbook &#8216;nginx&#8217;, &#8216;~&gt; 0.101.5&#8217; <\/p>\n<p>Install the cookbooks you specified in the Berksfile and their dependencies<\/p>\n<p> $ berks install <\/p>\n<p>Add the [&#8230;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[80],"tags":[],"_links":{"self":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/6537"}],"collection":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6537"}],"version-history":[{"count":2,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/6537\/revisions"}],"predecessor-version":[{"id":6539,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/6537\/revisions\/6539"}],"wp:attachment":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6537"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6537"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6537"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}