Include a directory of config files for a Vagrantfile - ruby

I have a Vagrantfile that has the following semi-standard setup:
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/focal64"
config.vm.network :forwarded_port, guest: 80, host: 8080, auto_correct: true
config.vm.network "private_network", ip: "192.168.56.40"
config.vm.hostname = "development.local"
config.vm.boot_timeout = 600
config.vm.provider "virtualbox" do |v|
v.name = "development.local"
v.memory = "1024"
v.check_guest_additions = true
end
config.vm.provision :shell, path: "bootstrap.sh"
end
My aim is to auto include files within a folder that configure the site on vagrant up.
For apache settings, I have managed to create a nice bash script that parses a folder and sets up sites-enabled for all the configs within a folder.
I would like to also share these folders inside the Vagrantfile without having to modify the core, much like apache parses the sites-enabled folder. This would mean I can easily share this box with others, without having to change the Vagrantfile every time I spin up a test environment and want to share a new folder.
The usual syntax is:
config.vm.synced_folder "../some-folder/", "/var/www/some-folder", owner: "www-data"
Using pseudocode, this is what I'm aiming for:
foreach([$files_in_$folder] as $synced_folder) {
require $synced_folder_config_file;
// ^ this would be a small config file
}
Note that the advantage of the small config file is that other things could be specified on a per-file bases (such as different owners/permissions etc).
Key things to do:
parse over folder contents
ensure that this config is executed as part of the vagrant up
I've barely touched ruby, so apologies if this is obvious.
Thanks

After some research and a lot of reprovisions and up/down/destroy:
Create appropriate files in the /synced-folders/, each consisting of something like:
config.vm.synced_folder "../development.local/", "/var/www/development.local", owner: "www-data"
Then, in your Vagrantfile:
Dir[File.dirname(__FILE__) + '/synced-folders/*.rb'].each {|file| eval File.read(file) }
This parses over the directory, and evals them.

Related

Vagrant is not syncing files

So I've been looking around a little bit for this issue, but maybe I lack something.
I freshly generated a Vagrant VM (With VirtualBox) but the files only seem to sync 1 time when the server loads/reloads.
I only have this in my configuration file, am I missing something here?
Vagrant.configure("2") do |config|
config.vm.box = "debian/stretch64"
config.vm.network "forwarded_port", guest: 25565, host: 25565
config.vm.provider "virtualbox" do |vb|
vb.memory = "8192"
end
end
I also tried with
config.vm.synced_folder ".", "/vagrant_files"
But that doesn't seem to change anything.
I don't have any errors on load, but the result is that when I add a file on the server, I don't see it in the project folder on my pc

Vagrant synced folder causes contents to be erased

I'm trying to add add an additional synced folder besides the default /vagrant.
I've read the documentation which indicates that this should be as simple as:
config.vm.synced_folder "/path/to/somewhere/on/host", "/path/to/guest_directory", create: true
When I add this to my Vagrantfile and then reprovision it, the guest_directory folder shows up in the expected place on the host, but it's empty. And the folder in the guest OS is also empty... which breaks my site because those are the website files. Interestingly, if I remove that from the Vagrantfile and reprovision again, the files reappear in the guest OS where they were originally.
Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/xenial64"
config.vm.network "private_network", ip: "192.168.33.99"
# NEITHER OF THESE WORK...
# config.vm.synced_folder "/Users/ESL/Sites/project/web__public_web", "/home/vagrant/web__public_web", create: true
# config.vm.synced_folder "./web__public_web", "/home/vagrant/web__public_web", type: "rsync", rsync__args: ["--verbose", "--archive", "--delete", "-z"], create: true
config.vm.provider "virtualbox" do |vb|
vb.memory = "2046"
end
end
You can see that I've tried a two different type: options and got the same wrong result with both. I also tried placing a symlink to the project files inside /vagrant/ and that didn't work either. (The broken symlink showed up in the host os directory instead of the files I want to access)
Here are a couple more details about my setup, just in case they're relevant:
In the guest OS the project files live in /home/vagrant/web__public_web but the document root is /srv/www/... which contains a symlink pointing to the former path.
VirtualBox: Version 5.2.18 r124319 (Qt5.6.3)
Vagrant: v2.1.0
OSX: 10.13.6
What am I doing wrong?
Each mount requires a unique id, if the box is already built you'll need to rebuild it.
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/xenial64"
config.vm.network "private_network", ip: "192.168.33.99"
config.vm.synced_folder "/Users/ESL/Sites/project/web__public_web", "/path/where/mounted/on/vm", id: "unique_id_1", type: "rsync", rsync__args: ["--verbose", "--archive", "--delete", "-z"], create: true
config.vm.synced_folder "/home/vagrant/web__public_web", "/path/where/mounted/on/vm2", id: "unique_id_2", type: "rsync", rsync__args: ["--verbose", "--archive", "--delete", "-z"], create: true
config.vm.provider "virtualbox" do |vb|
vb.memory = "2046"
end
end
I answered my own question...
It turns out the sync was working all along. But I misunderstood the directionality of the sync. I was expecting the files in the guest OS to show up in the host directory, but it's the other way around. The empty folder on the host directory was getting synced to the guest and wiping out all the files.
After I manually copied all of the files from the guest to the host directory, the same configurations worked as expected.
Bottom line: if you want to sync an existing guest folder with files in it, you have to manually move it into place on the host OS first.

Vagrant synced_folder /vagrant shared_folder missing

Hi I'm trying to provision my box using vagrant and ansible but I always encounter /vagrant/ansible/playbook.yml is missing. It's looking for a /vagrant directory. When I ssh inside my box the /vagrant does not exist. I'm not sure what happen but what I did was to sync all my local copy into a specific folder location inside my box. Below is a sample implementation I did
Vagrant.configure("2") do |config|
config.vm.define "ans", primary: true do |ans|
ans.vm.box = "ubuntu/xenial64"
ans.vm.network "forwarded_port", guest: 80, host: 8080
ans.vm.network "private_network", ip: "10.8.9.20", auto_network: true
ans.vm.synced_folder ".", "/var/www/"
ans.vm.hostname = "my_project"
ans.vm.provision "pre-build", type: "shell", :path => "ansible/bootstrap.sh"
ans.vm.provision "ansible_local" do |ansible|
ansible.playbook = "ansible/playbook.yml"
end
end
end
I'm getting an error in the ansible.playbook = "ansible/playbook.yml" it seems this line is looking under /vagrant folder which does not exist. What will be the workaround or fix for this? My playbook exist in this location /var/www/ansible/playbook.yml inside the box
By default, vagrant automatically add a shared folder from your current directory with /vagrant folder on the VM.
Because you have added
ans.vm.synced_folder ".", "/var/www/"
the current folder shared folder has been replaced from /vagrant to /var/www (you can easily verify that by removing the line from your vagrantfile)
do you really need to sync the whole current folder with /var/www ideally you would have your project files in a subdirectory that you will share in /var/www like
ans.vm.synced_folder "html/", "/var/www/"
and push all your html/csss/js files under the html folder (feel free to rename project or something else) and you'll not need to sync all the vagrant scripts and provisioning script with your web server folder.

Multi-machine Vagrant project not provisioning as per docs

I’ve trying to set up a multi-machine Vagrant project. According to the docs (https://www.vagrantup.com/docs/multi-machine/), provisioning is “outside in”, meaning any top-level provisioning scripts are executed before provisioning scripts in individual machine blocks.
The project contains a Laravel project, and a Symfony project. My Vagrantfile looks like this:
require "json"
require "yaml"
confDir = $confDir ||= File.expand_path("vendor/laravel/homestead", File.dirname(__FILE__))
homesteadYamlPath = "web/Homestead.yaml"
homesteadJsonPath = "web/Homestead.json"
afterScriptPath = "web/after.sh"
aliasesPath = "web/aliases"
require File.expand_path(confDir + "/scripts/homestead.rb")
Vagrant.configure(2) do |config|
config.vm.provision "shell", path: "init.sh"
config.vm.define "web" do |web|
web.ssh.forward_x11 = true
if File.exists? aliasesPath then
web.vm.provision "file", source: aliasesPath, destination: "~/.bash_aliases"
end
if File.exists? homesteadYamlPath then
Homestead.configure(web, YAML::load(File.read(homesteadYamlPath)))
elsif File.exists? homesteadJsonPath then
Homestead.configure(web, JSON.parse(File.read(homesteadJsonPath)))
end
if File.exists? afterScriptPath then
web.vm.provision "shell", path: afterScriptPath
end
end
config.vm.define "api" do |api|
api.vm.box = "ubuntu/trusty64"
api.vm.provider :virtualbox do |vb|
vb.customize ["modifyvm", :id, "--memory", "2048"]
end
api.vm.network "private_network", ip: "10.1.1.34"
api.vm.network "forwarded_port", guest: 80, host: 8001
api.vm.network "forwarded_port", guest: 3306, host: 33061
api.vm.network "forwarded_port", guest: 9200, host: 9201
api.vm.synced_folder "api", "/var/www/api"
api.vm.provision "shell", path: "api/provision.sh"
end
end
I have a block (web) for the Laravel project, where I’ve copied the contents of the Homestead-based Vagrantfile, and an api block that uses the “standard” Vagrant configuration.
To bootstrap the projects, I created a simple shell script (init.sh) that simply clones the Git repositories into git-ignored directories. Given the documentation says configuration works outside-in, I’d therefore expect that script to run, and then the machine-specific blocks, but this doesn’t seem to be happening. Instead, on vagrant up, I receive the following error:
There are errors in the configuration of this machine. Please fix the following errors and try again:
vm:
* A box must be specified.
It seems it’s still trying to provision the individual machines, before running the shell script. I know the shell script isn’t getting called as I added an echo statement to it. Instead, the terminal just outputs the following:
Bringing machine 'web' up with 'virtualbox' provider...
Bringing machine 'api' up with 'virtualbox' provider...
So how can I get Vagrant to run my shell script first? I think it’s failing because the web group is checking if my web/Homestead.yaml file exists and if so, use the values in there for configuring (including the box name), but as my shell script hasn’t been ran and hasn’t cloned the repository that file does not exist, so there is no box specified, which Vagrant complains about.
The issue is that you do not define a box for the web machine. You need to either define the box in the outer space like
config.vm.box = "ubuntu/trusty64"
if you plan to use the same box/OS for both machines or define in the web scope
web.vm.box = "another box"
EDIT
Using the provision property will run the script in the VM, which is not what you want here, as you want the script to run on your host. (and because it runs in the VM, it needs the VM to be booted first)
Vagrantfile is just a simple ruby script, so you could add your script or even an execution to it (from ruby call), a potential issue I could see is that you cannot guarantee the execution and specially that the execution of your init script will be complete before vagrant does it things on the VM.
A possibility is to use the vagrant trigger plugin and execute your shell script before the up event
config.trigger.before :up do
info "Dumping the database before destroying the VM..."
run "init.sh"
end
Running it this way, vagrant will wait for the script to be executed before it runs its part of the up command.
You would need to do some check in your script to make sure it runs only when needed, otherwise, it will run everytime you start the machine (invoking vagrant up), e.g. you could make a check on the presence of the yaml file

Using SaltStack grains file with Vagrant

I would like to use minion.d/*.conf to provision a vagrant machine.
Here is my Vagrant configuration:
Vagrant.configure("2") do |config|
## Choose your base box
config.vm.box = "precise64"
## For masterless, mount your salt file root
config.vm.synced_folder "salt/roots/", "/srv/salt/"
## Use all the defaults:
config.vm.provision :salt do |salt|
salt.minion_config = "salt/minion"
salt.run_highstate = true
salt.grains_config = "salt/minion.d/vagrant.conf"
end
end
After provisioning the Vagrant machine, I have errors with rendering SLS files since the minion.d/*.conf files are not being copied to the guest machine under :
/etc/salt/minion.d/
Should I make a sync config in the Vagrant configuration to co ?
Have you just tried mounting a synced folder to /etc/salt/grains?
## For masterless, mount your salt file root
config.vm.synced_folder "salt/roots/", "/srv/salt/"
config.vm.synced_folder "salt/grains.d/", "/etc/salt/grains.d/"
#Utah_Dave's solution will work just fine, or you can do the following (which is how I run it).
Filesystem:
/dev
Vagrantfile
salt-minion.conf
salt/
top.sls
my-awesome-state/init.sls
pillar/
top.sls
my-awesome-pillar.sls
Vagrantfile:
Vagrant.configure("2") do |config|
config.vm.box = "mafro/jessie64-au-salt"
# salt config directory & shared dir in /tmp
config.vm.synced_folder ".", "/srv/salt"
# setup the salt-minion
config.vm.provision :salt do |salt|
salt.minion_config = "salt-minion.conf"
end
end
salt-minion.conf
file_client: local
id: awesome
file_roots:
base:
- /srv/salt/salt
pillar_roots:
base:
- /srv/salt/pillar
Vagrant's implementation of salt.grains_config doesn't copy the file to the /etc/salt/minion.d folder as you might expect. Instead it copies the file to /etc/salt/grains.
To get the salt-minion to read this new grains file, you just need to add the following to your minion configuration:
/etc/salt/minion
include:
- /etc/salt/grains

Resources