Overriding Cookbook Attribute in Vagrantfile Custom JSON Data - maven

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"

Related

golang unknown revision module/vX.Y.Z and importing package properly

I have a golang application structure like this:
.
├── calc
│   ├── go.mod
│   ├── main.go
│   └── Makefile
├── go.mod
├── LICENSE
├── num
│   ├── go.mod
│   └── num.go
└── README.md
Where calc is an "application" where I'm importing the num package to add 2 numbers.
calc/go.mod
go 1.15
require github.com/github_username/goapp/num v0.2.1
num/go.mod
module github.com/github_username/goapp/num/v0.2.1
go 1.15
go.mod
module github.com/github_username/goapp/v0.2.1
go 1.15
When in /calc, and I run go run main.go, I get the following:
go: github.com/github_username/goapp/num#v0.2.1: reading github.com/github_username/goapp/num/num/go.mod at revision num/v0.2.1: unknown revision num/v0.2.1
What am I doing wrong? The github repo has the annotated tags.
For further context, I'm mimicking a production setup where we have six different mini golang services in folders such as calc, calc2, etc. where each "calc" service has a go.mod file.
module github.com/github_username/goapp/num/v0.2.1
Is nonsense. The semver version tag "v0.2.1" does not belong into the module name.
(Note that for major versions > 1, e.g. 4.3.1, the major version becomes part of the name like in module github.com/user/proj/folder/v4).
And one more: There are no source code belonging to the root go.mod so this module makes no sense whatsoever.
You really should not make that many modules.
Are you working with private repositories?
if yes, then you need to configure OAuth authentication:
export GITHUB_TOKEN=MY_GITHUB_TOKEN
git config --global url."https://${GITHUB_TOKEN}:x-oauth-basic#github.com/".insteadOf "https://github.com/"
Now, if you don't have the necessity to use private repositories!
Turn your repositories to the public that will solve the problem too.

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:

Require paths for rspec tests in a Ruby Gem

I am creating a simple Ruby Gem which is currently laid out as per the example in the Making your own gem documentation.
My directory structure:
.
├── Gemfile
├── Gemfile.lock
├── lib
│   ├── go_run
│   │   ├── parser.rb
│   │   └── runner.rb
│   └── go_run.rb
└── spec
├── go_run_spec.rb
├── parser_spec.rb
└── runner_spec.rb
I originally called the Runner class in lib/go_run/runner.rb just Runner, but now, as per the documented example I have namespaced it under GoRun::Runner. The code works. The problem is that now running bundle exec rspec spec/parser_spec.rb does not. It fails with:
/home/smurf/dev/ruby/go_run/lib/go_run/parser.rb:3:in `<top (required)>': uninitialized constant GoRun (NameError)
The 3rd line of that file is:
class GoRun::Parser
I am requireing the library code in spec/parser_spec.rb using require 'go_run/parser'.
I tried including it with require_relative '../lib/go_run/parser', but that produced the same error.
Does anybody know what I am doing wrong?
Update: I have uploaded the complete code on this branch: https://github.com/henrytk/go_run/tree/stackoverflow-43155117
The problem is originating in lib/go_run/parser.rb rather than from the test itself. Whenever Ruby finds the GoRun::Parser definition, it goes looking for GoRun in the constant lookup table, but it won't be there, and so the program exits with an error.
Note that using lib/go_run.rb as an entry point also will not work, because go_run/parser.rb is required before GoRun is defined.
Part of the problem is using GoRun as both the project level namespace, and an entry point class.
There are a couple of idioms you should consider to fix this situation:
Make GoRun a top level module, used purely for namespacing. Move the logic that lives in the current logic into its own class, for example go_run/cli.rb. The go_run.rb file is then kept as a sort of manifest file, that requires the classes of your project.
Use the nested module- and class syntax. This will define the outer module if it isn't already.
Use a spec_helper.rb file that bootstraps your project using require 'go_run', to make sure everything is properly loaded before running your tests.

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.

Using Chef Environments with Berkshelf

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.

Resources