Using Chef Environments with Berkshelf - vagrant

For my current project, I have an "Environment Cookbook" that has a folder structure like this:
.
├── Berksfile
├── Vagrantfile
├── environments
│   └── development.rb
├── metadata.rb
└── recipes
└── default.rb
In my Vagrantfile I use a chef_solo provisioner with the following configuration:
config.vm.provision :chef_solo do |chef|
chef.environments_path = 'environments'
chef.environment = 'development'
chef.run_list = [
"recipe[service-ldap::default]"
]
end
I have the vagrant-berkshelf plugin installed and the provisioning works, besides that I do not get any attributes that I have set in the environments/development.rb.
My question is, whether - and if yes, how - it is possible to use Chef Environments with Berkshelf or whether this is not part of the development workflow in Berkshelf. Maybe you could provide me a hint, how to achieve a workaround then.

Related

Exclude all except one subfolder for Rubocop

Let's say we have a folder called bin and it includes another subfolder bin/scripts besides other folders and top-level files.
We are looking to scan only the bin/scripts/**/* files and ignore everything else in the bin folder.
This pattern bellow excludes everything in that folder
AllCops:
TargetRubyVersion: 3.1.2
NewCops: enable
Exclude:
- "bin/**/*"
Use ERB to Template Your Exclusions
This is covered by the RuboCop documentation on including/excluding files when used in conjunction with the section on pre-processing using ERB. There might be a more elegant way to do this, but using ERB to add excluded items based on an inverted regular expression using Enumerable#grep_v on a Dir#glob just seems easiest to me.
This was tested with Ruby 3.1.2 and RuboCop v1.30.1, and "just works." Your mileage may vary with other versions or approaches.
AllCops:
TargetRubyVersion: 3.1.2
NewCops: enable
Exclude:
<% Dir.glob('bin/**/*').grep_v(%r{bin/scripts/}).each do |path| %>
- <%= path %>
<% end %>
With the template above in .rubocop.yml and a tree structure of:
.
├── bin
│   ├── bar.rb
│   ├── baz
│   │   └── quux.rb
│   └── scripts
│   └── wuuble
│   └── zub.rb
└── lib
└── foo.rb
RuboCop only checks:
lib/foo.rb
bin/scripts/wuuble/zub.rb

Automatic Ansible custom modules installation with Ansible Galaxy

Is there any nice way to use Ansible Galaxy order to install and enable Ansible (2.7.9) custom modules?
My requirement allows Ansible Galaxy to download the right Ansible role which embeds my custom module. Once ansible-galaxy install --roles-path ansible/roles/ -r roles/requirements.yml, I get the following structure (non-exhaustive):
├── ansible
│   ├── roles
│   │   ├── mymodule (being imported by Galaxy)
│   │   │   ├── library
│   │   │   │   └── mymodule.py
By looking this part of the documentation, it seems like my module is at the right place and does not require any further configuration: https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html?highlight=library#directory-layout
But when I found this part of the documentation I got confused. Is ANSIBLE_LIBRARY related to the custom modules?
DEFAULT_MODULE_PATH
Description: Colon separated paths in which Ansible will search for Modules.
Type: pathspec
Default: ~/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
Ini Section: defaults
Ini Key: library
Environment: ANSIBLE_LIBRARY
https://docs.ansible.com/ansible/latest/reference_appendices/config.html#default-module-path
When calling my module,
- name: Test of my Module
mymodule:
I get the following error:
ERROR! no action detected in task. This often indicates a misspelled module name, or incorrect module path.
I expected not to have to configure the ANSIBLE_LIBRARY and the module being automatically callable. Am I understanding correctly or should I also trick this var?
If your custom module is in a role, you need to include the role in your playbook, so at the very least:
---
- hosts: myhosts
roles:
- role: mymodule
tasks:
- name: Test of my Module
mymodule:

Trouble with chef-solo "Missing Cookbooks"

I am trying to run chef-solo, and I have the following configuration
/var/chef
├── cookbooks
│   ├── cc_db
│   │   ├── Berksfile
│   │   ├── Berksfile.lock
│   │   ├── chefignore
│   │   ├── metadata.rb
│   │   ├── recipes
│   │   │   └── default.rb
├── node.json
└── solo.rb
node.json
{
"run_list": [ "recipe[cc_db]" ]
}
solo.rb
file_cache_path "/var/chef"
cookbook_path "/var/chef/cookbooks"
json_attribs "/var/chef/node.json"
metadata.rb
depends 'database', '~> 5.1.2'
depends 'mysql2_chef_gem', '~> 1.0'
I've gotten this to work in a kitchen-test environment, but I'm trying it now on a different server using chef-solo.
Whenever I run:
chef-solo -c solo.rb
I get:
resolving cookbooks for run list: ["cc_db"]
================================================================================
Error Resolving Cookbooks for Run List:
================================================================================
Missing Cookbooks:
------------------
No such cookbook: database
Expanded Run List:
------------------
* cc_db
Platform:
---------
x86_64-linux
Running handlers:
[2016-09-20T15:34:05-04:00] ERROR: Running exception handlers
Running handlers complete
[2016-09-20T15:34:05-04:00] ERROR: Exception handlers complete
Chef Client failed. 0 resources updated in 02 seconds
[2016-09-20T15:34:05-04:00] FATAL: Stacktrace dumped to /var/chef/chef-stacktrace.out
[2016-09-20T15:34:05-04:00] FATAL: Please provide the contents of the stacktrace.out file if you file a bug report
[2016-09-20T15:34:05-04:00] ERROR: 412 "Precondition Failed"
[2016-09-20T15:34:05-04:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)
I'm confused because the database cookbook seem to be installed with berks, but chef isn't picking it up.
any help would be greatly appreciated.
thanks.
myles.
Chef doesn't directly integrate with Berkshelf, so chef-solo knows nothing about that. Normally you would use something like knife-solo which ties them together, but you could also do it manually. Run berks vendor /path/to/a/folder and then set that folder as the cookbook_path.
I ended up just going around the problem.
I set up a chef-server on a virtual host, and do some final level testing on that. I created nodes, bootstrapped them, then ran chef-client on the node.
I also don't have a very large server configuration, so I just uploaded the cookbooks and dependent cookbooks by hands. Which I'm pretty sure is why chef-zero was failing. At some point in the future I will get Berkshelf working in conjunction with everything to help ease the cookbook dependency process.

Simple pattern to export rake tasks defined in gem to the outside world upon installation

This question follows the "Make rake task from gem available everywhere?" for which I'm not fully satisfied with the Railties approach since it induces a dependency on Rails3 which seems to me overkilling compared to what I want.
Also, I dislike the idea to create an extra binary as suggested in this question
So, assuming I have the below layout:
.
├── CHANGELOG.md
├── Gemfile
├── Gemfile.lock
├── LICENCE.md
├── README.md
├── Rakefile
├── my_gem.gemspec
├── lib
│   ├── my_gem
│   │   ├── common.rb
│   │   ├── loader.rb
│   │   ├── tasks
│   │   │   └── sometasks.rake
│   │   └── version.rb
│   └── my_gem.rb
where lib/my_gem/tasks/sometasks.rake has some nested rake tasks definition:
#.....................
namespace :n1 do
#.....................
namespace :n2 do
desc "Tasks n1:n2:t1"
task :t1 do |t|
puts "Task 1"
end
desc "Tasks n1:n2:t2"
task :t2 do |t|
puts "Task 2"
end
end # namespace n1:n2
end # namespace n1
How can I easily share these tasks in another external Rakefile with a simple syntax such as require "my_gem/sometasks" once the gem is installed?
I tested the following configuration in a separate directory with success yet I still think it's a complicated syntax. Any help to simplify the load / include/ require would be welcome:
add a GemFile containing
gem 'my_gem', :path => '~/path/to/my_gem'
add a Rakefile with the following content:
require "my_gem"
load "my_gem/tasks/sometasks.rake"
desk "Test my_gem"
task :toto do |t|
puts "task toto"
end
In the above configuration, it works:
$> bundle exec rake -T
rake n1:n2:t1 # Task n1:n2:t1
rake n1:n2:t1 # Task n1:n2:t2
rake toto # Test my_gem
Yet if I get rid of .rake extension in the Rakefile, I have a load error
rake aborted!
LoadError: cannot load such file -- my_gem/tasks/sometasks
Any hint?
I found a way, inspired from Bundler to offer a simplified interface (and [gem_tasks.rb](https://github.com/bundler/bundler/blob/master/lib/bundler/gem_tasks.rb):
create a file lib/my_gem/sometasks_tasks.rb with an install_tasks method
require 'rake'
module MyGem
class SomeTasks
include Rake::DSL if defined? Rake::DSL
def install_tasks
load 'my_gem/tasks/sometasks.rake'
end
end
end
MyGem::SomeTasks.new.install_tasks
In the application’s Rakefile, it is now enough to add require 'my_gem/sometasks_tasks'

Overriding Cookbook Attribute in Vagrantfile Custom JSON Data

How do you access node.override using chef.json in a Vagrant file?
For example, using vagrant-berkshelf, I'm trying to install a particular Maven version based on Custom JSON Data in the Vagrantfile:
chef.json = {
'maven' => {
'version' => '3.0.5'
}
}
cookbooks\maven_custom\attributes\default.rb
default['maven']['version'] = "3.2.1"
cookbooks\maven_custom\recipes\default.rb
Chef::Log.info(node['maven']['version'])
When I run vagrant provision, the following gets printed out:
3.2.1
Additionally, I tried vagrant reload --provision, yet still saw "3.2.1" print out.
I would've expected 3.0.5 since I had (I thought) overridden it in my Vagrantfile.
How can I correctly extract the Vagrantfile's JSON value of "3.0.5"?
Not entirely clear what the question is, but I'll assume you're trying to write a wrapper cookbook that installs a more modern version of Maven.
The trick is to set "normal" attributes in the wrapper cookbook which will override the "default" attributes of maven cookbook. For more details read about chef's attribute precedence
This is a better than providing run-time parameters, for the following reasons:
You are writing a wrapper cookbook, so an attribute file would be the natural place to set values
The "maven" cookbook requires setting 4 attributes to specify a new Maven version.
Hope this helps.
Example
├── attributes
│   └── maven.rb
├── Berksfile
├── Berksfile.lock
├── metadata.rb
├── recipes
│   └── default.rb
└── Vagrantfile
metadata.rb
name 'maven_custom'
maintainer 'YOUR_NAME'
maintainer_email 'YOUR_EMAIL'
license 'All rights reserved'
description 'Installs/Configures maven_custom'
long_description 'Installs/Configures maven_custom'
version '0.1.0'
depends "apt"
depends "maven"
attributes/maven.rb
normal['maven']['version'] = 3
normal['maven']['3']['version'] = '3.2.1'
normal['maven']['3']['url'] = 'http://www.eu.apache.org/dist/maven/maven-3/3.2.1/binaries/apache-maven-3.2.1-bin.tar.gz'
normal['maven']['3']['checksum'] = 'cdee2fd50b2b4e34e2d67d01ab2018b051542ee759c07354dd7aed6f4f71675c'
recipes/default.rb
#
# Cookbook Name:: maven_custom
# Recipe:: default
#
include_recipe "apt"
include_recipe "maven"

Resources