From Fedora Project Wiki
Line 67: Line 67:
 
|}
 
|}
  
==== Building Vagrant plugins ====
+
== Building Vagrant plugins ==
  
 
A sample spec for building a Vagrant plugin would look like this:
 
A sample spec for building a Vagrant plugin would look like this:
Line 158: Line 158:
 
</pre>
 
</pre>
  
===== %prep =====
+
=== %prep ===
 
Since gems aren't an archive format that RPM recognizes, the first thing we have to do is explicitly use <code>gem unpack</code> to extract the source from the gem.  Then we call <code>%setup -n %{vagrant_plugin_name}-%{version}</code> to tell RPM what the directory the gem has unpacked into.  The [http://www.rpm.org/max-rpm/s1-rpm-inside-macros.html#S3-RPM-INSIDE-SETUP-T-OPTION <code>-T</code>] and [http://www.rpm.org/max-rpm/s1-rpm-inside-macros.html#S3-RPM-INSIDE-SETUP-D-OPTION <code>-D</code>] flags tell <code>%setup</code> that we've already unpacked the code
 
Since gems aren't an archive format that RPM recognizes, the first thing we have to do is explicitly use <code>gem unpack</code> to extract the source from the gem.  Then we call <code>%setup -n %{vagrant_plugin_name}-%{version}</code> to tell RPM what the directory the gem has unpacked into.  The [http://www.rpm.org/max-rpm/s1-rpm-inside-macros.html#S3-RPM-INSIDE-SETUP-T-OPTION <code>-T</code>] and [http://www.rpm.org/max-rpm/s1-rpm-inside-macros.html#S3-RPM-INSIDE-SETUP-D-OPTION <code>-D</code>] flags tell <code>%setup</code> that we've already unpacked the code
  
 
We then run <code>gem spec</code> to output the metadata from the gem into a file.  This <code>.gemspec</code> file will be used to rebuild the gem later.  If we need to modify the <code>.gemspec</code> (for instance, if the version of dependencies is wrong for Fedora or the <code>.gemspec</code> is using old, no longer supported fields) we would do it here.  Patches to the code itself can also be done here.
 
We then run <code>gem spec</code> to output the metadata from the gem into a file.  This <code>.gemspec</code> file will be used to rebuild the gem later.  If we need to modify the <code>.gemspec</code> (for instance, if the version of dependencies is wrong for Fedora or the <code>.gemspec</code> is using old, no longer supported fields) we would do it here.  Patches to the code itself can also be done here.
  
===== %build =====
+
=== %build ===
 
Next we build the gem. Because <code>%vagrant_plugin_install</code> only operates on gem archives, we next recreate the gem with <code>gem build</code>. The gem file that is created is then used by <code>%vagrant_plugin_install</code> to build and install the code into the temporary directory, which is <code>./%{gem_dir}</code> by default. We do this because the <code>%vagrant_plugin_install</code> command both builds and installs the code in one step so we need to have a temporary directory to place the built sources before installing them in <code>%install</code> section.
 
Next we build the gem. Because <code>%vagrant_plugin_install</code> only operates on gem archives, we next recreate the gem with <code>gem build</code>. The gem file that is created is then used by <code>%vagrant_plugin_install</code> to build and install the code into the temporary directory, which is <code>./%{gem_dir}</code> by default. We do this because the <code>%vagrant_plugin_install</code> command both builds and installs the code in one step so we need to have a temporary directory to place the built sources before installing them in <code>%install</code> section.
  
Line 175: Line 175:
  
  
===== %install =====
+
=== %install ===
 
Here we actually install into the <code>%{buildroot}</code>.  We create the directories that we need and then copy what was installed into the temporary directories into the <code>%{buildroot}</code> hierarchy.  Finally, if this ruby gem creates shared objects the shared objects are moved into the arch specific <code>%{gem_extdir_mri}</code> path.
 
Here we actually install into the <code>%{buildroot}</code>.  We create the directories that we need and then copy what was installed into the temporary directories into the <code>%{buildroot}</code> hierarchy.  Finally, if this ruby gem creates shared objects the shared objects are moved into the arch specific <code>%{gem_extdir_mri}</code> path.
  
  
 
[[Category:Packaging guidelines drafts]]
 
[[Category:Packaging guidelines drafts]]

Revision as of 11:48, 3 November 2015

Warning.png
This page is a draft only
It is still under construction and content may change. Do not rely on the information on this page.

Vagrant plugins are esentially RubyGems that are installed to a specific Vagrant plugin directory and that need to be registered in Vagrant plugin configuration file upon installation. As most of the RubyGems guidelines apply to them, this guide discusses only specifics in which Vagrant plugins differ.

Ruby Compatibility

Vagrant and its plugins current does not work with alternative Ruby interpreters. You do not need to specify the requirement on ruby package in plugins spec files though. Specify:

Requires: ruby(release)

Naming Guidelines

Plugins should follow upstream name that usually starts with vagrant-. Do not add the rubygem- prefix.

Macros

Vagrant plugins must be installed to certain standard locations. The vagrant package contains usuful macros that should be used to achieve that.

Macro Expanded path Usage
From vagrant; intended for Vagrant plugin packages.
%{vagrant_dir} %{_datadir}/vagrant Vagrant installation directory.
%{vagrant_plugin_conf_dir} %{_sharedstatedir}/vagrant Plugin configuration files.
%{vagrant_plugin_conf} %{vagrant_plugin_conf_dir}/plugins.json Configuration file for system-wide plugins.
%{vagrant_plugin_dir} %{vagrant_dir}/gems Common locations for Vagrant plugin gems.
%{vagrant_plugin_instdir} %{vagrant_plugin_dir}/gems/%{vagrant_plugin_name}-%{version} Directory with the actual content of the plugin.
%{vagrant_plugin_libdir} %{vagrant_plugin_instdir}/lib The lib folder of the plugin.
%{vagrant_plugin_cache} %{vagrant_plugin_dir}/cache/%{vagrant_plugin_name}-%{version}.gem The cached plugin.
%{vagrant_plugin_spec} %{vagrant_plugin_dir}/specifications/%{vagrant_plugin_name}-%{version}.gemspec The plugin's specification file.
%{vagrant_plugin_docdir} %{vagrant_plugin_dir}/doc/%{vagrant_plugin_name}-%{version} The rdoc documentation of the plugin.
%{vagrant_plugin_extdir} %{_libdir}/vagrant/gems/ruby/%{vagrant_plugin_name}-%{version} The directory for MRI Ruby plugin extensions. Currently unused.

Building Vagrant plugins

A sample spec for building a Vagrant plugin would look like this:

%global vagrant_plugin_name vagrant-registration

Name: %{vagrant_plugin_name}
Version: 0.0.19
Release: 2%{?dist}
Summary: Automatic guest registration for Vagrant
Group: Development/Languages
License: GPLv2
URL: https://rubygems.org/gems/vagrant-registration 
Source0: https://rubygems.org/gems/%{vagrant_plugin_name}-%{version}.gem
Requires(pre): shadow-utils
Requires(posttrans): vagrant
Requires(preun): vagrant
Requires: ruby(release)
Requires: ruby(rubygems) >= 1.3.6
Requires: vagrant
BuildRequires: ruby(release)
BuildRequires: rubygems-devel >= 1.3.6
BuildRequires: ruby 
BuildRequires: vagrant
BuildArch: noarch
Provides: vagrant(%{vagrant_plugin_name}) = %{version}

%description
Enables guests to be registered automatically which is especially useful
for RHEL or SLES guests.

%package doc
Summary: Documentation for %{name}
Group: Documentation
Requires: %{name} = %{version}-%{release}
BuildArch: noarch

%description doc
Documentation for %{name}.

%prep
gem unpack %{SOURCE0}

%setup -q -D -T -n  %{vagrant_plugin_name}-%{version}

gem spec %{SOURCE0} -l --ruby > %{vagrant_plugin_name}.gemspec

%build
# Create the gem as gem install only works on a gem file
gem build %{vagrant_plugin_name}.gemspec
%vagrant_plugin_install

%install
mkdir -p %{buildroot}%{vagrant_plugin_dir}
cp -a .%{vagrant_plugin_dir}/* \
        %{buildroot}%{vagrant_plugin_dir}/

# We can't run test suite because it requires virtualization
%check
pushd .%{vagrant_plugin_instdir}

popd

%pre
getent group vagrant >/dev/null || groupadd -r vagrant

%posttrans
%vagrant_plugin_register %{vagrant_plugin_name}

%preun
%vagrant_plugin_unregister %{vagrant_plugin_name}

%files
%license %{vagrant_plugin_instdir}/LICENSE.md
%{vagrant_plugin_instdir}/plugins/*
%{vagrant_plugin_libdir}
%exclude %{vagrant_plugin_cache}
%{vagrant_plugin_spec}

%files doc
%doc %{vagrant_plugin_instdir}/README.md
%doc %{vagrant_plugin_instdir}/CHANGELOG.md
%doc %{vagrant_plugin_docdir}
%{vagrant_plugin_instdir}/Rakefile
%{vagrant_plugin_instdir}/Gemfile
%{vagrant_plugin_instdir}/vagrant-registration.gemspec
%{vagrant_plugin_instdir}/tests

%changelog

%prep

Since gems aren't an archive format that RPM recognizes, the first thing we have to do is explicitly use gem unpack to extract the source from the gem. Then we call %setup -n %{vagrant_plugin_name}-%{version} to tell RPM what the directory the gem has unpacked into. The -T and -D flags tell %setup that we've already unpacked the code

We then run gem spec to output the metadata from the gem into a file. This .gemspec file will be used to rebuild the gem later. If we need to modify the .gemspec (for instance, if the version of dependencies is wrong for Fedora or the .gemspec is using old, no longer supported fields) we would do it here. Patches to the code itself can also be done here.

%build

Next we build the gem. Because %vagrant_plugin_install only operates on gem archives, we next recreate the gem with gem build. The gem file that is created is then used by %vagrant_plugin_install to build and install the code into the temporary directory, which is ./%{gem_dir} by default. We do this because the %vagrant_plugin_install command both builds and installs the code in one step so we need to have a temporary directory to place the built sources before installing them in %install section.

%vagrant_plugin_install macro accepts two additional options:

-n <gem_file>
Allows to override gem used for installation. This might get useful for converting legacy spec, so you might specify %{SOURCE0} as a gem for installation.
-d <install_dir>
Might override the gem installation destination. However we do not suggest to use this option.
Note.png
The %vagrant_plugin_install macro must not be used to install into the %{buildroot}


%install

Here we actually install into the %{buildroot}. We create the directories that we need and then copy what was installed into the temporary directories into the %{buildroot} hierarchy. Finally, if this ruby gem creates shared objects the shared objects are moved into the arch specific %{gem_extdir_mri} path.