Chef workflow for new cookbooks - workflow

While building my own cookbooks I find myself constantly within this cycle:
Change cookbook on my local computer
Upload modified cookbook to chef server
Run chef-client on remote machine
Repeat
Since I am new to chef, I repeat that cycle extremely often, but I find rather cumbersome uploading and downloading so frequently from the chef server.
How experienced chef users ease this cycle? I learnt Chef with the free hosted solution, but I am not sure if I should be better off using just Chef-solo and move back later to the hosted version once I have many servers and more experience with chef.
Is there maybe a workflow where I can quickly try changes to my cookbooks directly on my remote machine while using hosted Chef but without uploading them?

I do all my development locally on my laptop, using Vagrant. When the cookbook is ready, it gets pushed to it's new Git repository home and integrated into my production chef server infrastructure.
The following example runs nginx on a virtualbox image.
Example
Install vagrant plugins (only needs to be done once):
vagrant plugin install vagrant-omnibus
vagrant plugin install vagrant-berkshelf
vagrant plugin install vagrant-chef-zero
Use Berkshelf to generate a new application cookbook.
$ berks cookbook demo
create demo/files/default
create demo/templates/default
create demo/attributes
create demo/definitions
create demo/libraries
create demo/providers
create demo/recipes
create demo/resources
create demo/recipes/default.rb
create demo/metadata.rb
create demo/LICENSE
create demo/README.md
create demo/Berksfile
create demo/Thorfile
create demo/chefignore
create demo/.gitignore
run git init from "./demo"
create demo/Gemfile
create demo/Vagrantfile
Edit the following files (Details below):
Vagrantfile <-- Controls vagrant's operation
metadata.rb <-- List community cookbook dependencies
recipes/default.rb <-- Calls to community cookbook recipes and LWRPs
Running vagrant will startup a virtual machine that is provisioned using chef-client. The chef zero plugin will run a local embedded instance of chef-server. The berkself plugin is used to automatically load the cookbook dependencies.
vagrant up
The following command will rerun chef-client (following edits):
vagrant provision
Finally, the really big advantage of doing development, using local virtualization, is that you can tear everything down and build it again from scratch:
vagrant destroy -f && vagrant up
Vagrantfile
Controls vagrant's operation. In this case I'm only starting a single VM, provisioned using chef-client:
Vagrant.require_plugin "vagrant-omnibus"
Vagrant.require_plugin "vagrant-berkshelf"
Vagrant.require_plugin "vagrant-chef-zero"
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Box config
config.vm.box = "saucy64"
config.vm.box_url = "http://cloud-images.ubuntu.com/vagrant/saucy/current/saucy-server-cloudimg-amd64-vagrant-disk1.box"
# Virtualbox config
config.vm.provider :virtualbox do |vb|
vb.customize ["modifyvm", :id, "--memory", 1024]
end
# Networking config
config.vm.network "private_network", ip: "10.0.0.10"
# Plugin config
config.omnibus.chef_version = :latest
config.chef_zero.enabled = true
config.berkshelf.enabled = true
# Chef config
config.vm.provision :chef_client do |chef|
chef.add_recipe "demo"
end
end
The omnibus plugin is responsible for installing the desired version of chef. The Berkshelf plugin will download cookbook dependencies and when combined with chef-zero will upload cookbooks during each provision run.
metadata.rb
Add nginx as a cookbook dependency:
name 'demo'
maintainer 'YOUR_NAME'
maintainer_email 'YOUR_EMAIL'
license 'All rights reserved'
description 'Installs/Configures demo'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '0.1.0'
depends "nginx"
The Berksfile is preconfigured to load the cookbook dependencies, listed in the metadata file, from the community cookbook repository.
site :opscode
metadata
recipes/default.rb
Run the default nginx recipe
#
# Cookbook Name:: demo
# Recipe:: default
#
# Copyright (C) 2014 YOUR_NAME
#
# All rights reserved - Do Not Redistribute
#
include_recipe "nginx"

I go through that loop most of the time during my testings. But I also use Chef solo when I need to try several minor changes in a recipe. If you have a test machine with a local copy of your chef repo then you can try making changes there and running chef solo to see the results. This way there's no uploading.

Related

Manually run cloud-init on bare metal server

We have a cloud-config made for virtual servers and we want to remove the virtualization layer and have the same setup on bare metal server.
Is it possible to manually run that cloud-init user data script on the bare metal servers, after the server setup ? (OS install - Centos 7)
I have read about nocloud datasource for cloud-init and configuring os setup to fetch cloud-init data from an usb drive but for me it's not possible, I must find a solution to run run my user data via cloud-init manually after OS was installed
The NoCloud datasource is still the easiest way to accomplish this. As part of install (or directly after install), you could create a filesystem (or VFS) with the files needed for NoCloud. If that's too cumbersome, you can also create a file at /etc/cloud/cloud.cfg.d/99-mydata.cfg with something like:
datasource_list: [ NoCloud ]
datasource:
NoCloud:
meta-data:
instance-id: literallyanything
local-hostname: myhostname
user-data: |
#cloud-config
runcmd:
- echo "hello from cloud-init" > /var/tmp/hello
using your cloud-config rather than what I have there. See the docs example.
To have cloud-init run, it's easiest to reboot and let cloud-init run on next boot. Cloud-init isn't really intended to be run manually, but it can be done with something like:
cloud-init init --local
cloud-init init
cloud-init modules --mode=config
cloud-init modules --mode=final
cloud-init status --wait --long

verifying cookbooks for windows using opscode's hosted chef

I have few cookbooks which have to be verified only for Windows.Basically running the recipes and see
I am using opscode's hosted chef.
For doing this, which combination shall I use :
a) windows workstation(for uploading recipes to server), ubuntu chef client node.
b) windows workstation , windows chef client node.
I am actually very new to the chef.Please suggest me...
In your case for simply verifying Windows recipes/cookbooks work, I highly recommend using chef-solo. You don't need to set up an entire chef server to prove everything works (unless that requirement is being forced on you):
http://docs.opscode.com/chef_solo.html
Running is as simple as:
chef-solo -c C:/chef/solo.rb -j C:/chef/solo.json
Where solo.rb is your configuration file and solo.json contains your run list and attributes.
If you do need a chef server... it doesn't really matter if you run it on Windows or Linux, just choose whatever is going to be easiest for you. Regardless the client will need to be installed on your Windows workstation.
http://docs.opscode.com/install_workstation.html
http://docs.opscode.com/install_windows.html

Vagrant & Chef - Postgresql not starting on reboot

I decided to create my own chef script to install Postgres. The installation works perfectly fine, but postgres doesn't start on boot when I vagrant reload
Here's my recipes/default.rb:
include_recipe "apt"
apt_repository 'apt.postgresql.org' do
uri 'http://apt.postgresql.org/pub/repos/apt'
distribution node["lsb"]["codename"] + '-pgdg'
components ['main', node["postgres"]["version"]]
key 'http://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc'
action :add
end
package 'postgresql-' + node["postgres"]["version"] do
action :install
end
file "/etc/postgresql/#{node['postgres']['version']}/main/postgresql.conf" do
action :delete
end
link "/etc/postgresql/#{node['postgres']['version']}/main/postgresql.conf" do
to node["postgres"]["conf_path"]
action :create
notifies :reload, "service[postgresql]", :delayed
end
service "postgresql" do
action [:enable, :start]
supports :status=>true, :restart=>true, :start => true, :stop => true, :reload=>true
end
And here's my attributes/default.rb:
default["postgres"]["version"] = "9.3"
default["postgres"]["conf_path"] = "/home/vagrant/postgres/postgresql.conf"
Any help would be greatly appreciated!!
============ EDIT 1 ============
Here is the output when running vagrant up for the first time with chef.log_level = :debug: http://pastebin.com/w8Lp8gzv
Here is /etc/init.d/postgresql: http://pastebin.com/dQ5Zb1yj
Here is /var/log/postgresql/postgresql-9.3-main.log: http://pastebin.com/0Y2RhWvL
============ EDIT 2 ============
I'm now fairly confident that it's my postgresql.conf file, which looks like: http://pastebin.com/rjX89iU0
shared_buffers might be too high...
When you run vagrant reload, is the Chef Client running? I suspect not. Mitchell changed the behavior in a recent version of vagrant to only provision if the machine hasn't already been provisioned. This information is stored in the .vagrant directory in your working directory. In short, since you already provisioned your machine with vagrant up, it is not provisioned when you run vagrant reload.
You run vagrant up - this is actually going to run vagrant up --provision, which executes the Chef Client provisioner on the node, executing your Chef Recipe.
You run vagrant reload - this actually runs vagrant up --no-provision, because the .vagrant. directory indicates the machine has already been provisioned. So your machine is rebooted, but the Chef Client provisioner is not executed.
Solution
Run vagrant reload with the --provision flag
vagrant reload --provision
Notes
This still doesn't explain why upstart (or whatever you're using to ensure the postgres service is running at boot) isn't starting the server for your automatically. In order to answer that question, I'll need to see more information. Can you set the chef.log_level = :debug in your Vagrantfile and update your question with the output? It would also be helpful to see the init.d script this postgres installer creates, and any log output from /var/log related to postgres.
Alright, it looks like Postgresql doesn't play nice with postgresql.conf being a symbolic link. Copying the file instead did the trick.
Turns out the postgresql was starting before the postgersql.conf file was mounted
If you're starting services with Upstart that depend on something in Vagrant's shared folders, have your upstart conf file listen for the vagrant-mounted event.
# /etc/init/start-postgresql.conf
start on vagrant-mounted
script
# commands to start postgresql...
end script
The vagrant-mounted event is emitted after Vagrant is done setting up shared folders, this way you can restart dependent services after vagrant reload without having to run your provisioners again.

How to deploy a meteor application to my own server?

How to deploy a meteor application to my own server?
flavour 1: the development and deployment server are the same;
flavour 2: the development server is one (maybe my localhost) and the deployment server is another (maybe a VPS in the cloud);
flavour 3: I want to make a "meteor hosting" domain, just like "meteor.com". Is it possible? How?
Update:
I'm running Ubuntu and I don't want to "demeteorize" the application. Thank you.
Meteor documentation currently says:
"[...] you need to provide Node.js 0.8 and a MongoDB server. You can
then run the application by invoking node, specifying the HTTP port
for the application to listen on, and the MongoDB endpoint."
So, among the several ways to install Node.js, I got it up and running following the best advice I found, which is basically unpacking the latest version available directly in the official Node.JS website, already compiled for Linux (64 bits, in my case):
# Does NOT need to be root user:
# create directory
mkdir -p ~/.nodes && cd ~/.nodes
# download latest Node.js distribution
curl -O http://nodejs.org/dist/v0.10.13/node-v0.10.13-linux-x64.tar.gz
# unpack it
tar -xzf node-v0.10.13-linux-x64.tar.gz
# discard it
rm node-v0.10.13-linux-x64.tar.gz
# rename unpacked folder
mv node-v0.10.13-linux-x64 0.10.13
# create symlink
ln -s 0.10.13 current
# add path to PATH
export PATH="~/.nodes/current/bin:$PATH"
# check
node --version
npm --version
And to install MongoDB, I simply followed the instructions in the MongoDB manual available in the Documentation section of its official website:
# Needs to be root user (apply "sudo" if not at root shell)
apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10
echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | tee /etc/apt/sources.list.d/10gen.list
apt-get update
apt-get install mongodb-10gen
The server is ready to run Meteor applications! For deployment, the main "issue" is where the "bundle" operation happens. We need to run meteor bundle command from inside the application source files tree. For example:
cd ~/leaderboard
meteor bundle leaderboard.tar.gz
If the deployment will happen in another server (flavour 2), we need to upload the bundle tar.gz file to it, using sftp, ftp, or any other file transfer method. Once the file is there, we follow both Meteor documentation and the README file which is magically included in the root of the bundle tree:
# unpack the bundle
tar -xvzf leaderboard.tar.gz
# discard tar.gz file
rm leaderboard.tar.gz
# rebuild native packages
pushd bundle/programs/server/node_modules
rm -r fibers
npm install fibers#1.0.1
popd
# setup environment variables
export MONGO_URL='mongodb://localhost'
export ROOT_URL='http://example.com'
export PORT=3000
# start the server
node main.js
If the deployment will be in the same server (flavour 1), the bundle tar.gz file is already there, and we don't need to recompile the native packages. (Just jump the corresponding section above.)
Cool! With these steps, I've got the "Leaderboard" example deployed to my custom server, not "meteor.com"... (only to learn and value their services!)
I still have to make it run on port 80 (I plan to use NginX for this), persist environment variables, start Node.JS dettached from terminal, et cetera... I am aware this setup in a "barely naked" one... just the base, the first step, basic foundation stones.
The application has been "manually" deployed, without taking advantage of all meteor deploy command magic features... I've seen people published their "meteor.sh" and "meteoric.sh" and I am following the same path... create a script to emulate the "single command deploy" feature... aware that in the near future all this stuff will be part of the pioneer Meteor explorers only, as it will grow into a whole Galaxy! and most of these issues will be an archaic thing of the past.
Anyway, I am very happy to see how fast the deployed application runs in the cheapest VPS ever, with a surprisingly low latency and almost instant simultaneous updates in several distinct browsers. Fantastic!
Thank you!!!
Try Meteor Up too
With that you can deploy into any Ubuntu server. This uses meteor build command internally. And used by many for deploying production apps.
I created Meteor Up to allow developers to deploy production quality Meteor apps until Galaxy comes.
I would recommend flavor two with a separate deployment server. Separation of concerns leads to a more stable environment for your code and its easier to debug.
To do it, there's the excellent Meteoric bash script that helps you deploy to Amazon's EC2 or your own server.
As for how to roll your own meteor.com, I suggest you break that out into it's own StackOverflow question as it's not related. Plus, I can't answer it :)
I done with it few days ago. I deployed my Meteor application to my own server on the DigitalOcean. I used Meteor Up tool for managing deploys and Nginx on the server to serve the app.
It's very simple to use. You should install meteor up with the command:
npm install -g mup
Then create the folder for deployment configuration and go to the created directory. Then run mup init command. It will created two configuration files. We are have interest for mup.json file. It have configurations for deployment process. It's looks like this:
{
// Server authentication info
"servers": [
{
"host": "hostname",
"username": "root",
"password": "password",
// or pem file (ssh based authentication)
//"pem": "~/.ssh/id_rsa",
// Also, for non-standard ssh port use this
//"sshOptions": { "port" : 49154 },
// server specific environment variables
"env": {}
}
],
// Install MongoDB on the server. Does not destroy the local MongoDB on future setups
"setupMongo": true,
// WARNING: Node.js is required! Only skip if you already have Node.js installed on server.
"setupNode": true,
// WARNING: nodeVersion defaults to 0.10.36 if omitted. Do not use v, just the version number.
"nodeVersion": "0.10.36",
// Install PhantomJS on the server
"setupPhantom": true,
// Show a progress bar during the upload of the bundle to the server.
// Might cause an error in some rare cases if set to true, for instance in Shippable CI
"enableUploadProgressBar": true,
// Application name (no spaces).
"appName": "meteor",
// Location of app (local directory). This can reference '~' as the users home directory.
// i.e., "app": "~/Meteor/my-app",
// This is the same as the line below.
"app": "/Users/arunoda/Meteor/my-app",
// Configure environment
// ROOT_URL must be set to https://YOURDOMAIN.com when using the spiderable package & force SSL
// your NGINX proxy or Cloudflare. When using just Meteor on SSL without spiderable this is not necessary
"env": {
"PORT": 80,
"ROOT_URL": "http://myapp.com",
"MONGO_URL": "mongodb://arunoda:fd8dsjsfh7#hanso.mongohq.com:10023/MyApp",
"MAIL_URL": "smtp://postmaster%40myapp.mailgun.org:adj87sjhd7s#smtp.mailgun.org:587/"
},
// Meteor Up checks if the app comes online just after the deployment.
// Before mup checks that, it will wait for the number of seconds configured below.
"deployCheckWaitTime": 15
}
After you fill all data fields you can start the setup process with command mup setup. It will setup your server.
After sucessfull setup you can deploy your app. Just type mup deploy in the console.
Another alternative is to just develop on your own server to start with.
I just created a Digital Ocean box and then connected my Cloud9 IDE account.
Now, I can develop right on the machine in a Cloud IDE and deployment is easy--just copying files.
I created a tutorial that shows exactly how my set up works.
I had a lot of trouble with meteor up, so I decided writing my own deploy script. I also added additional info how to set up nginx or mongodb. Hope it helps!
See /sh folder in repository
What the script meteor-deploy.sh does:
Select environment (./meteor-deploy.sh for staging, ./meteor-deploy.sh prod for production)
Build and bundle production version of the meteor app
Copy bundle to server
SSH into server
Do a mongodump to backup database
Stop the running app
Unpack bundle
Overwrite app files
Re-install app node package dependencies
Start the app (uses forever)
Tested for the following server configurations:
Ubuntu 14.04.4 LTS
meteor --version 1.3.2.4
node --version v0.10.41
npm --version 3.10.3

Vagrant Box Breaking After Knife Cookbook Installs

I'm a Vagrant n00b who's having issues getting Vagrant and Chef's knife command to play nice together as I'm setting up a pretty simple CentOS LAMP box using chef-solo.
Here's a quick rundown of ths issue:
I've created a basic Vagrantfile using the CentOS 6.3 w/ Chef base box on vagrantbox.es. You can see the basics in this gist.
I've downloaded all the cookbooks via knife cookbook site install nameofcookbook using a configuration that puts them in ./chef/cookbooks.
I've successfully run vagrant up to You can see the basics in this gist.
I've tested apache, php, etc. All good.
Now comes the trick: with the VM running, I run knife to add another package (in this case i3).
From here on, Vagrant fails to perform various tasks in the VM:
When I run vagrant provision I get an error like this
The chef binary (either `chef-solo` or `chef-client`) was not found on
the VM and is required for chef provisioning. Please verify that chef
is installed and that the binary is available on the PATH.
When I run vagrant halt I get an error that the ssh command exited with a non-zero error code.
I am able to run vagrant ssh however, and confirm that (a) chef-solo does, in fact, exist in the box and (b) I can shutdown via the commandline in the box.
When I run vagrant up I get an error like this:
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!
mkdir -p /vagrant</li>
I'm stumped. I've had this happen on two boxes already, and I know that Knife and Vagrant should be able to play well together.
What am I doing wrong?
Any help much appreciated, I've very excited about digging into Vagrant!
chef.add_recipe "sudo"
Nuked your sudo file after the first run.
Add the appropriate json to your vagrant file for your vagrant user.
Something like:
config.vm.provision :chef_solo do |chef|
# add your recipes
# chef.add_recipe "foo"
# chef.add_role "bar"
chef.json = {
"authorization" => {
"sudo" => {
"users" => [ "vagrant" ],
"passwordless" => true,
}
}
}
end