├── .github ├── pull_request_template.md └── workflows │ ├── release.yml │ ├── ruby.yml │ ├── ruby3.yml │ └── security.yml ├── .gitignore ├── .rubocop.yml ├── .yardopts ├── CHANGELOG.md ├── CODEOWNERS ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── bin ├── build ├── build_host_info ├── build_requirements ├── inspect ├── render ├── repo ├── ship ├── sign └── vanagon ├── docs ├── CONTRIBUTING.md ├── DESIGN.md ├── STYLEGUIDE.md └── USING_VANAGON.md ├── examples ├── components │ ├── component1.rb │ └── component2.rb ├── platforms │ ├── platform.rb │ └── windows-platform.rb ├── projects │ └── project.rb └── resources │ └── windows │ └── wix │ ├── appdatafiles.wxs │ ├── componentgroup.wxs.erb │ ├── customactions.wxs.erb │ ├── project.wxs.erb │ ├── properties.wxs.erb │ ├── registryEntries.wxs.erb │ └── sequences.wxs.erb ├── extras └── completions │ ├── vanagon.bash │ └── vanagon.zsh ├── lib ├── git │ ├── basic_submodules.rb │ └── rev_list.rb ├── makefile.rb ├── vanagon.rb └── vanagon │ ├── cli.rb │ ├── cli │ ├── build.rb │ ├── build_host_info.rb │ ├── build_requirements.rb │ ├── completion.rb │ ├── dependencies.rb │ ├── inspect.rb │ ├── list.rb │ ├── render.rb │ ├── ship.rb │ └── sign.rb │ ├── common.rb │ ├── common │ ├── pathname.rb │ └── user.rb │ ├── component.rb │ ├── component │ ├── dsl.rb │ ├── rules.rb │ ├── source.rb │ └── source │ │ ├── git.rb │ │ ├── http.rb │ │ ├── local.rb │ │ └── rewrite.rb │ ├── driver.rb │ ├── engine │ ├── always_be_scheduling.rb │ ├── base.rb │ ├── docker.rb │ ├── ec2.rb │ ├── hardware.rb │ ├── local.rb │ └── pooler.rb │ ├── environment.rb │ ├── errors.rb │ ├── extensions │ ├── hashable.rb │ ├── ostruct │ │ └── json.rb │ ├── set │ │ └── json.rb │ └── string.rb │ ├── logger.rb │ ├── patch.rb │ ├── platform.rb │ ├── platform │ ├── deb.rb │ ├── defaults │ │ ├── amazon-2-aarch64.rb │ │ ├── amazon-2023-aarch64.rb │ │ ├── amazon-2023-x86_64.rb │ │ ├── amazon-7-aarch64.rb │ │ ├── debian-10-amd64.rb │ │ ├── debian-11-aarch64.rb │ │ ├── debian-11-amd64.rb │ │ ├── debian-12-aarch64.rb │ │ ├── debian-12-amd64.rb │ │ ├── debian-8-amd64.rb │ │ ├── debian-8-i386.rb │ │ ├── el-6-i386.rb │ │ ├── el-6-x86_64.rb │ │ ├── el-7-x86_64.rb │ │ ├── el-8-aarch64.rb │ │ ├── el-8-ppc64le.rb │ │ ├── el-8-x86_64.rb │ │ ├── el-9-aarch64.rb │ │ ├── el-9-ppc64le.rb │ │ ├── el-9-x86_64.rb │ │ ├── fedora-36-x86_64.rb │ │ ├── fedora-38-x86_64.rb │ │ ├── fedora-40-x86_64.rb │ │ ├── osx-11-arm64.rb │ │ ├── osx-11-x86_64.rb │ │ ├── osx-12-arm64.rb │ │ ├── osx-12-x86_64.rb │ │ ├── osx-13-arm64.rb │ │ ├── osx-13-x86_64.rb │ │ ├── osx-14-arm64.rb │ │ ├── osx-14-x86_64.rb │ │ ├── redhatfips-7-x86_64.rb │ │ ├── redhatfips-8-x86_64.rb │ │ ├── redhatfips-9-x86_64.rb │ │ ├── sles-12-x86_64.rb │ │ ├── sles-15-x86_64.rb │ │ ├── solaris-11-i386.rb │ │ ├── solaris-11-sparc.rb │ │ ├── ubuntu-18.04-aarch64.rb │ │ ├── ubuntu-18.04-amd64.rb │ │ ├── ubuntu-20.04-aarch64.rb │ │ ├── ubuntu-20.04-amd64.rb │ │ ├── ubuntu-22.04-aarch64.rb │ │ ├── ubuntu-22.04-amd64.rb │ │ ├── ubuntu-24.04-aarch64.rb │ │ └── ubuntu-24.04-amd64.rb │ ├── dsl.rb │ ├── osx.rb │ ├── rpm.rb │ ├── rpm │ │ ├── aix.rb │ │ ├── eos.rb │ │ ├── sles.rb │ │ └── wrl.rb │ ├── solaris_10.rb │ ├── solaris_11.rb │ └── windows.rb │ ├── project.rb │ ├── project │ └── dsl.rb │ ├── utilities.rb │ └── utilities │ ├── extra_files_signer.rb │ └── shell_utilities.rb ├── resources ├── Makefile.erb ├── deb │ ├── changelog.erb │ ├── conffiles.erb │ ├── control.erb │ ├── dirs.erb │ ├── docs.erb │ ├── install.erb │ ├── postinst.erb │ ├── postrm.erb │ ├── preinst.erb │ ├── prerm.erb │ ├── rules.erb │ └── triggers.erb ├── osx │ ├── postinstall.erb │ ├── preinstall.erb │ ├── project-installer.xml.erb │ └── uninstaller.tool.erb ├── rpm │ └── project.spec.erb ├── solaris │ ├── 10 │ │ ├── depend.erb │ │ ├── pkginfo.erb │ │ ├── postinstall.erb │ │ ├── preinstall.erb │ │ ├── preremove.erb │ │ └── proto.erb │ └── 11 │ │ └── p5m.erb └── windows │ ├── nuget │ ├── chocolateyInstall.ps1 │ ├── chocolateyUninstall.ps1 │ └── project.nuspec.erb │ └── wix │ ├── directorylist.wxs.erb │ └── filter.xslt.erb ├── spec ├── fixtures │ ├── component │ │ ├── invalid-test-fixture.json │ │ ├── mcollective.service │ │ └── test-fixture.json │ ├── files │ │ ├── fake_dir.tar.gz │ │ ├── fake_dir │ │ │ └── fake_file.txt │ │ ├── fake_file.txt │ │ ├── fake_file.txt.erb │ │ ├── fake_file_ext.7z │ │ ├── fake_file_ext.bz │ │ ├── fake_file_ext.bz2 │ │ ├── fake_file_ext.cpio │ │ ├── fake_file_ext.gz │ │ ├── fake_file_ext.rar │ │ ├── fake_file_ext.tar │ │ ├── fake_file_ext.tar.bz2 │ │ ├── fake_file_ext.tar.gz │ │ ├── fake_file_ext.tar.xz │ │ ├── fake_file_ext.tbz │ │ ├── fake_file_ext.tbz2 │ │ ├── fake_file_ext.tgz │ │ ├── fake_file_ext.txz │ │ ├── fake_file_ext.xz │ │ ├── fake_file_ext.z │ │ ├── fake_file_ext.zip │ │ └── fake_nested_dir │ │ │ └── fake_dir │ │ │ └── fake_file.txt │ └── wix │ │ └── resources │ │ └── windows │ │ └── wix │ │ ├── file-1.wxs │ │ ├── file-2.wxs │ │ ├── file-3.wxs.erb │ │ ├── file-4.wxs.erb │ │ ├── include │ │ └── include-sample-1.wxs │ │ ├── project.filter.xslt.erb │ │ ├── project.wxs │ │ └── ui │ │ ├── bitmaps │ │ └── bitmap.bmp │ │ └── ui-sample-1.wxs ├── lib │ ├── git │ │ └── rev_list_spec.rb │ ├── makefile_spec.rb │ └── vanagon │ │ ├── cli_spec.rb │ │ ├── common │ │ ├── pathname_spec.rb │ │ └── user_spec.rb │ │ ├── component │ │ ├── dsl_spec.rb │ │ ├── rules_spec.rb │ │ ├── source │ │ │ ├── git_spec.rb │ │ │ ├── http_spec.rb │ │ │ ├── local_spec.rb │ │ │ └── rewrite_spec.rb │ │ └── source_spec.rb │ │ ├── component_spec.rb │ │ ├── driver_spec.rb │ │ ├── engine │ │ ├── always_be_scheduling_spec.rb │ │ ├── base_spec.rb │ │ ├── docker_spec.rb │ │ ├── ec2_spec.rb │ │ ├── hardware_spec.rb │ │ ├── local_spec.rb │ │ └── pooler_spec.rb │ │ ├── environment_spec.rb │ │ ├── extensions │ │ ├── ostruct │ │ │ └── json_spec.rb │ │ ├── set │ │ │ └── json_spec.rb │ │ └── string_spec.rb │ │ ├── platform │ │ ├── deb_spec.rb │ │ ├── dsl_spec.rb │ │ ├── osx_spec.rb │ │ ├── rpm │ │ │ └── aix_spec.rb │ │ ├── rpm_spec.rb │ │ ├── solaris_10_spec.rb │ │ ├── solaris_11_spec.rb │ │ └── windows_spec.rb │ │ ├── platform_spec.rb │ │ ├── project │ │ └── dsl_spec.rb │ │ ├── project_spec.rb │ │ ├── utilities │ │ ├── extra_files_signer_spec.rb │ │ └── shell_utilities_spec.rb │ │ └── utilities_spec.rb └── spec_helper.rb └── vanagon.gemspec /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | Please add all notable changes to the "Unreleased" section of the CHANGELOG. -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Gem release 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v1 14 | - name: Build gem 15 | uses: scarhand/actions-ruby@master 16 | with: 17 | args: build *.gemspec 18 | - name: Publish gem 19 | uses: scarhand/actions-ruby@master 20 | env: 21 | RUBYGEMS_AUTH_TOKEN: ${{ secrets.RUBYGEMS_AUTH_TOKEN }} 22 | with: 23 | args: push *.gem 24 | 25 | -------------------------------------------------------------------------------- /.github/workflows/ruby.yml: -------------------------------------------------------------------------------- 1 | name: Ruby 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v3 12 | - name: Set up Ruby 2.7 13 | uses: ruby/setup-ruby@v1 14 | with: 15 | ruby-version: '2.7' 16 | - name: Build and test with Rake 17 | run: | 18 | gem install bundler -v 2.4.22 19 | bundle install --jobs 4 --retry 3 20 | bundle exec rake 21 | -------------------------------------------------------------------------------- /.github/workflows/ruby3.yml: -------------------------------------------------------------------------------- 1 | name: Ruby3 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | strategy: 8 | fail-fast: false 9 | matrix: 10 | os: [ubuntu-latest] 11 | ruby: [ '3.0', '3.1', '3.2'] 12 | runs-on: ${{ matrix.os }} 13 | steps: 14 | - uses: actions/checkout@v3 15 | - name: Set up Ruby 3.x 16 | uses: ruby/setup-ruby@v1 17 | with: 18 | ruby-version: ${{ matrix.ruby }} 19 | bundler-cache: true 20 | - run: bundle exec rake 21 | -------------------------------------------------------------------------------- /.github/workflows/security.yml: -------------------------------------------------------------------------------- 1 | name: Security 2 | on: 3 | workflow_dispatch: 4 | push: 5 | branches: 6 | - main 7 | jobs: 8 | scan: 9 | name: Mend Scanning 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: checkout repo content 13 | uses: actions/checkout@v3 14 | with: 15 | fetch-depth: 1 16 | - name: setup ruby 17 | uses: ruby/setup-ruby@v1 18 | with: 19 | ruby-version: 2.7 20 | # setup a package lock if one doesn't exist, otherwise do nothing 21 | - name: check lock 22 | run: '[ -f "Gemfile.lock" ] && echo "package lock file exists, skipping" || bundle lock' 23 | # install java 24 | - uses: actions/setup-java@v3 25 | with: 26 | distribution: 'temurin' # See 'Supported distributions' for available options 27 | java-version: '17' 28 | # download mend 29 | - name: download_mend 30 | run: curl -o wss-unified-agent.jar https://unified-agent.s3.amazonaws.com/wss-unified-agent.jar 31 | - name: run mend 32 | run: java -jar wss-unified-agent.jar 33 | env: 34 | WS_APIKEY: ${{ secrets.MEND_API_KEY }} 35 | WS_WSS_URL: https://saas-eu.whitesourcesoftware.com/agent 36 | WS_USERKEY: ${{ secrets.MEND_TOKEN }} 37 | WS_PRODUCTNAME: RE 38 | WS_PROJECTNAME: ${{ github.event.repository.name }} 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Now that there is a gemfile, RVM ignores rvmrc in parent directories, so a local one is required 2 | # to work around that. Which we don't want committed, so we can ignore it here. 3 | /.rvmrc 4 | 5 | .bundle/ 6 | Gemfile.lock 7 | Gemfile.local 8 | .rspec 9 | 10 | vanagon_hosts.log 11 | 12 | /.project 13 | .idea/ 14 | .ruby-version 15 | .ruby-gemset 16 | 17 | # emacs backup files 18 | *~ 19 | 20 | .yardoc/ 21 | doc/ 22 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --readme README.md 2 | --charset utf-8 3 | --markup markdown 4 | lib/**/*.rb 5 | bin/* 6 | - 7 | **/*.md 8 | LICENSE 9 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # This repo is owned by Puppet Release Engineering 2 | 3 | * @puppetlabs/release-engineering @puppetlabs/vanagon-maintainers 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source ENV['GEM_SOURCE'] || "https://rubygems.org" 2 | 3 | def location_for(place) 4 | if place =~ /^(git[:@][^#]*)#(.*)/ 5 | [{ git: $1, branch: $2, require: false }] 6 | elsif place =~ /^file:\/\/(.*)/ 7 | ['>= 0', { path: File.expand_path($1), require: false }] 8 | else 9 | [place, { require: false }] 10 | end 11 | end 12 | 13 | # Accommodate dependencies from the Vanagon Gemspec 14 | gemspec 15 | 16 | # Confine EC2 engine dependencies 17 | group "ec2-engine" do 18 | gem "aws-sdk", "~> 3.1.0", require: false 19 | end 20 | 21 | # "lock_manager" is specified in development dependencies, to allow 22 | # the use of unreleased versions of "lock_manager" during development. 23 | group(:development, :test) do 24 | gem 'debug', '>= 1.0.0' 25 | gem 'fakefs' 26 | gem 'json' 27 | gem 'lock_manager', *location_for(ENV['LOCK_MANAGER_LOCATION'] || '>= 0') 28 | gem 'packaging', *location_for(ENV['PACKAGING_LOCATION'] || '~> 0.99') 29 | gem 'rake', require: false 30 | gem 'rspec', '~> 3.0', require: false 31 | gem 'rubocop', '~> 1.0', require: false 32 | gem 'rubocop-rake', require: false 33 | gem 'rubocop-rspec', require: false 34 | gem 'simplecov', require: false 35 | gem 'webmock', '~> 3.18' 36 | gem 'yard', require: false 37 | end 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014-2015 Puppet Labs 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/setup' 2 | require 'bundler/gem_tasks' 3 | require 'rspec/core/rake_task' 4 | require 'rubocop/rake_task' 5 | require 'yard' 6 | 7 | desc 'Test Vanagon' 8 | namespace :test do 9 | require 'rspec/core/rake_task' 10 | RSpec::Core::RakeTask.new do |task| 11 | task.rspec_opts = %(--format documentation --color --require spec_helper) 12 | end 13 | 14 | desc 'Test Vanagon and calculate test coverage' 15 | task :coverage do 16 | ENV['COVERAGE'] = 'true' 17 | Rake::Task['test:spec'].invoke 18 | end 19 | end 20 | 21 | desc 'Run RuboCop' 22 | RuboCop::RakeTask.new(:rubocop) do |task| 23 | task.options << '--display-cop-names' 24 | end 25 | 26 | desc 'Generate doc using Yard' 27 | YARD::Rake::YardocTask.new 28 | 29 | desc 'Run all spec tests and linters' 30 | task check: %w[test:spec rubocop] 31 | 32 | task default: :check 33 | -------------------------------------------------------------------------------- /bin/build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'vanagon/logger' 4 | 5 | script = File.basename($0) 6 | 7 | VanagonLogger.info "#{script}: Warning: use of stand alone '#{script}' command is deprecated and may be removed. 8 | Use: 'vanagon #{script}' instead." 9 | 10 | exec "vanagon", script, *ARGV 11 | -------------------------------------------------------------------------------- /bin/build_host_info: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'vanagon/logger' 4 | 5 | script = File.basename($0) 6 | 7 | VanagonLogger.info "#{script}: Warning: use of stand alone '#{script}' command is deprecated and may be removed. 8 | Use: 'vanagon #{script}' instead." 9 | 10 | exec "vanagon", script, *ARGV 11 | -------------------------------------------------------------------------------- /bin/build_requirements: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'vanagon/logger' 4 | 5 | script = File.basename($0) 6 | 7 | VanagonLogger.info "#{script}: Warning: use of stand alone '#{script}' command is deprecated and may be removed. 8 | Use: 'vanagon #{script}' instead." 9 | 10 | exec "vanagon", script, *ARGV 11 | -------------------------------------------------------------------------------- /bin/inspect: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'vanagon/logger' 4 | 5 | script = File.basename($0) 6 | 7 | VanagonLogger.info "#{script}: Warning: use of stand alone '#{script}' command is deprecated and may be removed. 8 | Use: 'vanagon #{script}' instead." 9 | 10 | exec "vanagon", script, *ARGV 11 | -------------------------------------------------------------------------------- /bin/render: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'vanagon/logger' 4 | 5 | script = File.basename($0) 6 | 7 | VanagonLogger.info "#{script}: Warning: use of stand alone '#{script}' command is deprecated and may be removed. 8 | Use: 'vanagon #{script}' instead." 9 | 10 | exec "vanagon", script, *ARGV 11 | -------------------------------------------------------------------------------- /bin/repo: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'vanagon/logger' 4 | 5 | ENV["PROJECT_ROOT"] = Dir.pwd 6 | 7 | # Begin warning: This ship script is an internal tool. 8 | # This is not intended to function outside of Puppet Labs' infrastructure. 9 | # This presumes packages for this ref have already been build and shipped. 10 | # End of warning. 11 | 12 | # repo_target will allow us to be more granular with the selection of repos that will be constructed 13 | # if we have not built debs or rpms, the packaging repo will fail when creating repos 14 | if ARGV[0] 15 | repo_target = ARGV[0].downcase 16 | end 17 | 18 | require 'packaging' 19 | Pkg::Util::RakeUtils.load_packaging_tasks 20 | case repo_target 21 | when 'rpm' 22 | Pkg::Util::RakeUtils.invoke_task('pl:jenkins:rpm_repos') 23 | when 'deb' 24 | Pkg::Util::RakeUtils.invoke_task('pl:jenkins:deb_repos') 25 | when 'none' 26 | VanagonLogger.warn "Skipping repo generation since repo target is set to 'none'" 27 | else 28 | Pkg::Util::RakeUtils.invoke_task('pl:jenkins:rpm_repos') 29 | Pkg::Util::RakeUtils.invoke_task('pl:jenkins:deb_repos') 30 | end 31 | -------------------------------------------------------------------------------- /bin/ship: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'vanagon/logger' 4 | 5 | script = File.basename($0) 6 | 7 | VanagonLogger.info "#{script}: Warning: use of stand alone '#{script}' command is deprecated and may be removed. 8 | Use: 'vanagon #{script}' instead." 9 | 10 | exec "vanagon", script, *ARGV 11 | -------------------------------------------------------------------------------- /bin/sign: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'vanagon/logger' 4 | 5 | script = File.basename($0) 6 | 7 | VanagonLogger.info "#{script}: Warning: use of stand alone '#{script}' command is deprecated and may be removed. 8 | Use: 'vanagon #{script}' instead." 9 | 10 | exec "vanagon", script, *ARGV 11 | -------------------------------------------------------------------------------- /bin/vanagon: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | load File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "vanagon.rb")) 4 | 5 | vanagon = Vanagon::CLI.new 6 | 7 | vanagon.run(vanagon.parse(ARGV)) 8 | -------------------------------------------------------------------------------- /docs/STYLEGUIDE.md: -------------------------------------------------------------------------------- 1 | To make our project and component config files consistent and readable, file contents should be laid out using the following five sections, with each section commented using the following section headers: 2 | 3 | # Source-Related Metadata 4 | 5 | This section consists of any metadata related to the upstream sources or patch additions we require, including: 6 | 7 | * Version 8 | * Source URI 9 | * Patches 10 | * md5sums for the sources 11 | 12 | # Package Dependency Metadata 13 | 14 | This section contains metadata about the interaction between packages, including: 15 | 16 | * Runtime requirements 17 | * pkg.replaces 18 | * pkg.conflicts 19 | 20 | # Build requirements 21 | 22 | This section is only focused on listing build-time requirements for the software: 23 | 24 | * build_requires 25 | 26 | # Build-time configuration 27 | 28 | This section contains customizations for how the package gets configured and compiled, including: 29 | 30 | * Configure options 31 | * PATH/CFLAGS/LDFLAGS and other environment variable settings 32 | 33 | # Build Commands 34 | 35 | This section consists of the shell commands needed to configure, build, and install the software. If customizations are needed on a per-platform basis, they should come from the use of variables that were defined in previous sections. 36 | 37 | * pkg.configure 38 | * pkg.build 39 | * pkg.install 40 | -------------------------------------------------------------------------------- /examples/components/component1.rb: -------------------------------------------------------------------------------- 1 | component "component1" do |pkg, settings, platform| 2 | pkg.version "1.2.3" 3 | pkg.md5sum "abcd1234" 4 | pkg.url "http://my-file-store.my-app.example.com/component1-1.2.3.tar.gz" 5 | pkg.mirror "http://mirror-01.example.com/component1-1.2.3.tar.gz" 6 | pkg.mirror "http://mirror-02.example.com/component1-1.2.3.tar.gz" 7 | pkg.mirror "http://mirror-03.example.com/component1-1.2.3.tar.gz" 8 | 9 | pkg.build_requires "tar" 10 | 11 | if platform.is_deb? 12 | pkg.build_requires "zlib1g-dev" 13 | elsif platform.is_rpm? 14 | pkg.build_requires "zlib-devel" 15 | end 16 | 17 | pkg.configure do 18 | ["./configure --prefix=#{settings[:prefix]} "] 19 | end 20 | 21 | pkg.build do 22 | ["#{platform[:make]}"] 23 | end 24 | 25 | pkg.install do 26 | ["#{platform[:make]} install"] 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /examples/components/component2.rb: -------------------------------------------------------------------------------- 1 | component "component2" do |pkg, settings, platform| 2 | pkg.ref "1.2.3" 3 | pkg.url "git://git.example.com/my-app/component2.git" 4 | pkg.mirror "https://git.example.com/my-app/component2.git" 5 | pkg.mirror "git@git.example.com:my-app/component2.git" 6 | 7 | pkg.build_requires "component1" 8 | 9 | pkg.install do 10 | ["#{settings[:bindir]}/component1 install --configdir=#{settings[:sysconfdir]} --mandir=#{settings[:mandir]}"] 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /examples/platforms/platform.rb: -------------------------------------------------------------------------------- 1 | platform "debian-7-amd64" do |plat| 2 | plat.servicedir "/etc/init.d" 3 | plat.defaultdir "/etc/default" 4 | plat.servicetype "sysv" 5 | plat.codename "wheezy" 6 | 7 | plat.provision_with "export DEBIAN_FRONTEND=noninteractive; apt-get update -qq; apt-get install -qy --no-install-recommends build-essential devscripts make quilt pkg-config debhelper " 8 | plat.install_build_dependencies_with "DEBIAN_FRONTEND=noninteractive; apt-get install -qy --no-install-recommends " 9 | end 10 | -------------------------------------------------------------------------------- /examples/platforms/windows-platform.rb: -------------------------------------------------------------------------------- 1 | # For windows platforms this example assumes use of chocolatey and cygwin 2 | platform "windows-2012r2-x86" do |plat| 3 | plat.servicetype "windows" 4 | 5 | # We use chocolatey by default to install build dependancies and provision things. 6 | # This can be overridden easily 7 | plat.provision_with "C:/ProgramData/chocolatey/bin/choco.exe install -y mingw-w64 -version 5.2.0 -debug --no-progress" 8 | plat.provision_with "C:/ProgramData/chocolatey/bin/choco.exe install -y Wix310 -version 3.10.2 -debug -x86 --no-progress" 9 | 10 | plat.install_build_dependencies_with "C:/ProgramData/chocolatey/bin/choco.exe install -y --no-progress" 11 | 12 | plat.make "/usr/bin/make" 13 | plat.patch "TMP=/var/tmp /usr/bin/patch.exe --binary" 14 | 15 | plat.platform_triple "i686-unknown-mingw32" 16 | 17 | plat.package_type "msi" 18 | end 19 | -------------------------------------------------------------------------------- /examples/projects/project.rb: -------------------------------------------------------------------------------- 1 | project "my-app" do |proj| 2 | # Project level settings our components will care about 3 | proj.setting(:prefix, "/opt/my-app") 4 | proj.setting(:sysconfdir, "/etc/my-app") 5 | proj.setting(:logdir, "/var/log/my-app") 6 | proj.setting(:bindir, File.join(proj.prefix, "bin")) 7 | proj.setting(:libdir, File.join(proj.prefix, "lib")) 8 | proj.setting(:includedir, File.join(proj.prefix, "include")) 9 | proj.setting(:datadir, File.join(proj.prefix, "share")) 10 | proj.setting(:mandir, File.join(proj.datadir, "man")) 11 | proj.setting(:artifactory_url, "https://artifactory.delivery.puppetlabs.net/artifactory") 12 | proj.setting(:buildsources_url, "#{proj.artifactory_url}/generic/buildsources") 13 | 14 | if platform.is_windows? 15 | proj.setting(:company_name, "BananaLand Inc.") 16 | proj.setting(:company_id, "BananaLand") 17 | proj.setting(:common_product_id, "MyAppInstaller") 18 | proj.setting(:service_name, "my-app-service") 19 | proj.setting(:product_id, "my-app") 20 | proj.setting(:upgrade_code, "SOME_GUID") 21 | if platform.architecture == "x64" 22 | proj.setting(:win64, "yes") 23 | else 24 | proj.setting(:win64, "no") 25 | end 26 | end 27 | 28 | proj.description "This app does some things." 29 | proj.version "1.2.3" 30 | proj.license "ASL 2.0" 31 | proj.vendor "Me " 32 | proj.homepage "https://www.my-app.com" 33 | proj.requires "glibc" 34 | 35 | proj.component "component1" 36 | proj.component "component2" 37 | 38 | # Here we rewrite public http urls to use our internal source host instead. 39 | # Something like https://www.openssl.org/source/openssl-1.0.0r.tar.gz gets 40 | # rewritten as 41 | # https://artifactory.delivery.puppetlabs.net/artifactory/generic/buildsources/openssl-1.0.0r.tar.gz 42 | # 43 | # @deprecated 2017-04-07 - Ryan McKern 44 | # This functionality has been replaced with Component Mirrors. This feature 45 | # will be removed before Vanagon 1.0.0, but for now it will add all rewritten 46 | # URLs/URIs to the list of mirrors 47 | # 48 | # proj.register_rewrite_rule 'http', proj.buildsources_url 49 | 50 | # Here we rewrite public git urls to use our internal git mirror It turns 51 | # urls that look like git://github.com/puppetlabs/puppet.git into 52 | # git://github.delivery.puppetlabs.net/puppetlabs-puppet.git 53 | # 54 | # @deprecated 2017-04-07 - Ryan McKern 55 | # This functionality has been replaced with Component Mirrors. This feature 56 | # will be removed before Vanagon 1.0.0, but for now it will add all rewritten 57 | # URLs/URIs to the list of mirrors 58 | # 59 | # proj.register_rewrite_rule 'git', Proc.new { |url| 60 | # match = url.match(/github.com\/(.*)$/) 61 | # "git://github.delivery.puppetlabs.net/#{match[1].gsub('/', '-')}" if match 62 | # } 63 | 64 | # directory adds a directory (and its contents) to the package that is created 65 | proj.directory proj.prefix 66 | proj.directory proj.sysconfdir 67 | proj.directory proj.logdir 68 | end 69 | -------------------------------------------------------------------------------- /examples/resources/windows/wix/appdatafiles.wxs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /examples/resources/windows/wix/componentgroup.wxs.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | 15 | 16 | 18 | 19 | 20 | 21 | <%- get_services.each do |service| -%> 22 | 23 | <%- end -%> 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /examples/resources/windows/wix/customactions.wxs.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 15 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /examples/resources/windows/wix/project.wxs.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 18 | 19 | Installer" 23 | Comments="<%= @homepage %>" 24 | Compressed="yes" 25 | Platform="<%= @platform.architecture %>" /> 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /examples/resources/windows/wix/properties.wxs.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 14 | 17 | 18 | 21 | 22 | 26 | 29 | 32 | 33 | 40 | 41 | 42 | 43 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /examples/resources/windows/wix/registryEntries.wxs.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 17 | 18 | 22 | 23 | 26 | <%- if @platform.architecture == "x64" -%> 27 | 31 | 36 | <%- else %> 37 | 42 | <%- end -%> 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /examples/resources/windows/wix/sequences.wxs.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | CMDLINE_INSTALLDIR 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /extras/completions/vanagon.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | _vanagon() 4 | { 5 | local cur prev projects commands template_arg_commands 6 | 7 | # COMREPLY is an array variable used to store completions 8 | # the completion mechanism uses COMPRELY to display its contents as completions 9 | # COMP_WORDS is an array of all the words typed after the name of the program 10 | # COMP_CWORD is an index of the COMP_WORDS array pointing to the current word 11 | COMPREPLY=() 12 | cur="${COMP_WORDS[COMP_CWORD]}" 13 | prev="${COMP_WORDS[COMP_CWORD-1]}" 14 | projects=($({ vanagon list -r | sed 1d; } 2>/dev/null)) 15 | commands="build build_host_info build_requirements completion inspect list render sign ship help" 16 | template_arg_commands="build build_host_info build_requirements inspect render " 17 | 18 | # completes with a project if the previous word was a command in template_arg_commands 19 | if [[ $template_arg_commands =~ (^| )$prev($| ) ]] ; then 20 | _vanagon_avail_templates_projects=$({ vanagon list -r | sed 1d; } 2>/dev/null) 21 | # compgen generates completions filtered based on what has been typed by the user 22 | COMPREPLY=( $(compgen -W "${_vanagon_avail_templates_projects}" -- "${cur}") ) 23 | fi 24 | 25 | # allows multiple platforms to be tab completed 26 | if [[ ${#COMP_WORDS[@]} -gt 3 ]] ; then 27 | _vanagon_avail_templates_platforms=$({ vanagon list -l | sed 1d; } 2>/dev/null) 28 | COMPREPLY=( $(compgen -W "${_vanagon_avail_templates_platforms}" -- "${cur}") ) 29 | fi 30 | 31 | if [[ $1 == $prev ]] ; then 32 | # only show top level commands we are at root 33 | COMPREPLY=( $(compgen -W "${commands}" -- "${cur}") ) 34 | fi 35 | } 36 | 37 | # assign tab complete function `_vanagon ` to `vanagon` command 38 | complete -F _vanagon vanagon 39 | -------------------------------------------------------------------------------- /extras/completions/vanagon.zsh: -------------------------------------------------------------------------------- 1 | _vanagon() 2 | { 3 | local line commands template_arg_commands projects 4 | 5 | commands="build build_host_info build_requirements completion inspect list render sign ship help" 6 | template_arg_commands=("build" "build_host_info" "build_requirements" "inspect" "render") 7 | projects=($({ vanagon list -r | sed 1d; } 2>/dev/null)) 8 | 9 | # '%p:globbed-files:' sets completion to only offer files matching a 10 | # described pattern. 11 | zstyle ':completion:*' file-patterns '%p:globbed-files:' 12 | 13 | # arguments function provides potential completions to zsh 14 | # specs are of the form n:message:action 15 | _arguments -C \ 16 | ": :(${commands})" \ 17 | "*::arg:->args" 18 | 19 | # (Ie)prevents "invalid subscript" 20 | if ((template_arg_commands[(Ie)$line[1]])); then 21 | _vanagon_template_sub_projects 22 | fi 23 | if [[ $projects =~ (^| )$line[2]($| ) ]]; then 24 | _vanagon_template_sub_platforms 25 | fi 26 | } 27 | 28 | _vanagon_template_sub_projects() 29 | { 30 | # -W look in certain path but don't append path to tab compelte 31 | # -g enables file matching pattern 32 | # (:r) removes the file extension `.rb` from the completion 33 | _arguments "1: :_files -W $(PWD)/configs/projects/ -g '*.rb(:r)'" 34 | } 35 | 36 | _vanagon_template_sub_platforms() 37 | { 38 | _arguments "*: :_files -W $(PWD)/configs/platforms/ -g '*.rb(:r)'" 39 | } 40 | # compdef registeres the completion function: compdef 41 | compdef _vanagon vanagon 42 | -------------------------------------------------------------------------------- /lib/git/basic_submodules.rb: -------------------------------------------------------------------------------- 1 | require 'git' 2 | 3 | module BasicSubmodulePrimitives 4 | # Extend Git::Lib to support shotgunning submodules. This command 5 | # is not smart, and it has very poor support for submodule options. 6 | # For example, you can't pass any arguments to the handful of submodule 7 | # options that accept them (like --depth). We may extend it later, 8 | # but for rev. 0001, simply initializing them will suffice 9 | def update_submodules(**options) 10 | arr_opts = ['update'] 11 | options.each_pair do |k, v| 12 | arr_opts << "--#{k}" if v 13 | end 14 | Dir.chdir(@git_work_dir) do 15 | command('submodule', arr_opts) 16 | end 17 | end 18 | end 19 | 20 | module BasicSubmodules 21 | # @example Initialize all git submodules 22 | # >> repo = Git.clone("git@github.com:puppetlabs/facter.git", "facter", path: Dir.mktmpdir) 23 | # => 24 | # >> repo.checkout "3.1.3 25 | # => 26 | # >> repo.update_submodules(init: true) 27 | # => 28 | # @param [Hash] options any options to pass to `git submodule update` 29 | # @option options [Boolean] :init whether to initialize submodules when updating them 30 | # @option options [Boolean] :use the submodule's remote-tracking branch instead of superproject's SHA1 sum 31 | # @option options [Boolean] :no-fetch don't fetch new objects from the remote site. 32 | # @option options [Boolean] :force remove submodule's working tree even if modified 33 | # @option options [Boolean] :checkout checkout submodules in detached HEAD state 34 | # @option options [Boolean] :merge merge recorded commit for submodule into the current branch of the submodule 35 | # @option options [Boolean] :rebase rebase current branch of submodule onto the commit recorded in the superproject 36 | # @option options [Boolean] :recursive recurse into nested submodules 37 | # @return options [String] any output produced by `git` when submodules are initialized 38 | def update_submodules(**options) 39 | self.lib.update_submodules(**options) 40 | end 41 | end 42 | 43 | module Git 44 | class Lib 45 | include BasicSubmodulePrimitives 46 | end 47 | end 48 | 49 | module Git 50 | class Base 51 | include BasicSubmodules 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /lib/git/rev_list.rb: -------------------------------------------------------------------------------- 1 | require 'git' 2 | 3 | module LibRevList 4 | def rev_list(committish = nil, opts = {}) 5 | arr_opts = [] 6 | 7 | opts.each do |k, v| 8 | # allow for passing, say, :max-count or :max_count 9 | k = k.to_s 10 | k.tr!('_', '-') 11 | if v && v.to_s.downcase == 'true' 12 | arr_opts << "--#{k}" 13 | elsif v 14 | arr_opts << "--#{k}=#{v}" 15 | end 16 | end 17 | 18 | arr_opts << committish if committish 19 | 20 | command('rev-list', arr_opts) 21 | end 22 | end 23 | 24 | module Git 25 | class Lib 26 | include LibRevList 27 | end 28 | end 29 | 30 | module Git 31 | class Base 32 | def rev_list(committish = nil, opts = {}) 33 | lib.rev_list(committish, opts) 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/makefile.rb: -------------------------------------------------------------------------------- 1 | class Makefile 2 | # The Rule class defines a single Makefile rule. 3 | # 4 | # @see http://www.gnu.org/software/make/manual/make.html#Rule-Introduction 5 | class Rule 6 | # @!attribute [rw] target 7 | # @return [String] The target generated by this rule. 8 | attr_accessor :target 9 | 10 | # @!attribute [rw] dependencies 11 | # @return [Array] A list of dependencies that this rule depends on. 12 | attr_accessor :dependencies 13 | 14 | # @!attribute [rw] recipe 15 | # @return [Array] A list of commands to execute upon invocation of this rule. 16 | attr_accessor :recipe 17 | 18 | # Create a new Makefile rule. When a block is provided then it is called and passed the 19 | # newly created Rule object. 20 | # 21 | # @overload initialize(target, dependencies: [], recipe: []) 22 | # @param target [String] target 23 | # @param dependencies [Array]] 24 | # @param recipe [Array] 25 | # 26 | # @overload initialize(target, dependencies: [], recipe: [], &block) 27 | # @param target [String] target 28 | # @param dependencies [Array]] 29 | # @param recipe [Array] 30 | # @yieldparam rule [Makefile::Rule] 31 | # 32 | # @example Providing a block to #initialize 33 | # newrule = Makefile::Rule.new("test", dependencies: ["all"]) do |rule| 34 | # rule.recipe = [ 35 | # "make test", 36 | # "make cpplint", 37 | # ] 38 | # end 39 | def initialize(target, dependencies: [], recipe: [], &block) 40 | @target = target 41 | @dependencies = dependencies 42 | @recipe = recipe 43 | 44 | yield(self) if block 45 | end 46 | 47 | # @return [String, Nil] the name of all dependencies for a given rule, 48 | # flattened and joined for a Makefule target 49 | def flatten_dependencies 50 | return nil if dependencies.empty? 51 | dependencies.flatten.join("\s") 52 | end 53 | 54 | # @return [String] the base Rule for a Makefile target, including 55 | # all dependencies. 56 | def base_target 57 | ["#{target}:", dependencies].flatten.compact.join("\s") 58 | end 59 | 60 | def compounded_recipe 61 | Array(recipe) 62 | .compact 63 | .map { |line| "\t#{line.gsub("\n", "\n\t")}\n" } 64 | .join 65 | end 66 | 67 | # Format this rule as a Makefile rule. 68 | # 69 | # Recipes that have multiline statements will have tabs inserted after each 70 | # newline to ensure that the recipe is parsed as part of a single makefile rule. 71 | # 72 | # @return [String] 73 | def format 74 | [base_target, compounded_recipe].flatten.join("\n") 75 | end 76 | alias to_s format 77 | end 78 | end 79 | -------------------------------------------------------------------------------- /lib/vanagon.rb: -------------------------------------------------------------------------------- 1 | require 'time' 2 | 3 | LIBDIR = __dir__ 4 | VANAGON_ROOT = File.join(__dir__, "..") 5 | BUILD_TIME = Time.now.iso8601 6 | VANAGON_VERSION = Gem.loaded_specs["vanagon"].version.to_s 7 | 8 | $:.unshift(LIBDIR) unless 9 | $:.include?(File.dirname(__FILE__)) || $:.include?(LIBDIR) 10 | 11 | require 'vanagon/cli' 12 | require 'vanagon/driver' 13 | -------------------------------------------------------------------------------- /lib/vanagon/cli.rb: -------------------------------------------------------------------------------- 1 | require 'docopt' 2 | require 'json' 3 | 4 | require 'vanagon/extensions/ostruct/json' 5 | require 'vanagon/extensions/set/json' 6 | require 'vanagon/extensions/hashable' 7 | 8 | require 'vanagon/cli/build' 9 | require 'vanagon/cli/build_host_info' 10 | require 'vanagon/cli/build_requirements' 11 | require 'vanagon/cli/completion' 12 | require 'vanagon/cli/inspect' 13 | require 'vanagon/cli/list' 14 | require 'vanagon/cli/render' 15 | require 'vanagon/cli/ship' 16 | require 'vanagon/cli/sign' 17 | require 'vanagon/cli/dependencies' 18 | 19 | require 'vanagon/logger' 20 | 21 | 22 | class Vanagon 23 | class InvalidArgument < StandardError 24 | end 25 | 26 | class CLI 27 | DOCUMENTATION = <<~DOCOPT.freeze 28 | Usage: 29 | vanagon []... 30 | 31 | Commands are: 32 | build build a package given a project and platform 33 | build_host_info print information about build hosts 34 | build_requirements print external packages required to build project 35 | completion outputs path to tab completion script 36 | inspect a build dry-run, printing lots of information about the build 37 | list shows a list of available projects and platforms 38 | render create local versions of packaging artifacts for project 39 | sign sign a package 40 | ship upload a package to a distribution server 41 | dependencies write json file to STDOUT that shows all required gems for a given project and platform 42 | help print this help 43 | DOCOPT 44 | 45 | def parse(argv) # rubocop:disable Metrics/AbcSize 46 | parsed_options = parse_options(argv) 47 | sub_command = parsed_options[''] 48 | sub_argv = parsed_options[''] 49 | 50 | case sub_command 51 | when 'build' 52 | @sub_parser = Vanagon::CLI::Build.new 53 | when 'build_host_info' 54 | @sub_parser = Vanagon::CLI::BuildHostInfo.new 55 | when 'build_requirements' 56 | @sub_parser = Vanagon::CLI::BuildRequirements.new 57 | when 'completion' 58 | @sub_parser = Vanagon::CLI::Completion.new 59 | when 'inspect' 60 | @sub_parser = Vanagon::CLI::Inspect.new 61 | when 'render' 62 | @sub_parser = Vanagon::CLI::Render.new 63 | when 'list' 64 | @sub_parser = Vanagon::CLI::List.new 65 | when 'sign' 66 | @sub_parser = Vanagon::CLI::Sign.new 67 | when 'ship' 68 | @sub_parser = Vanagon::CLI::Ship.new 69 | when 'dependencies' 70 | @sub_parser = Vanagon::CLI::Dependencies.new 71 | when 'help' 72 | puts DOCUMENTATION 73 | exit 0 74 | else 75 | VanagonLogger.error "vanagon: Error: unknown command: \"#{sub_command}\"\n\n#{DOCUMENTATION}" 76 | exit 1 77 | end 78 | 79 | raw_options = @sub_parser.parse(sub_argv) 80 | options = @sub_parser.options_translate(raw_options) 81 | @sub_parser.options_validate(options) 82 | return options 83 | end 84 | 85 | def run(options) 86 | @sub_parser.run(options) 87 | end 88 | 89 | # Do validation of options 90 | def options_validate(options) 91 | options 92 | end 93 | 94 | # Provide a translation from parsed docopt options to older optparse options 95 | def options_translate(docopt_options) 96 | docopt_options 97 | end 98 | 99 | private 100 | 101 | def parse_options(argv) 102 | Docopt.docopt(DOCUMENTATION, { argv: argv, options_first: true }) 103 | rescue Docopt::Exit => e 104 | VanagonLogger.error e.message 105 | exit 1 106 | end 107 | end 108 | end 109 | -------------------------------------------------------------------------------- /lib/vanagon/cli/build.rb: -------------------------------------------------------------------------------- 1 | require 'docopt' 2 | require 'vanagon/logger' 3 | 4 | class Vanagon 5 | class CLI 6 | class Build < Vanagon::CLI 7 | DOCUMENTATION = <<~DOCOPT.freeze 8 | Usage: 9 | build [options] [] 10 | 11 | Options: 12 | -h, --help Display help 13 | -c, --configdir DIRECTORY Configuration directory [default: #{Dir.pwd}/configs] 14 | -e, --engine ENGINE Custom engine to use [default: always_be_scheduling] 15 | -o, --only-build COMPONENT,COMPONENT,... 16 | Only build listed COMPONENTs 17 | -p, --preserve [RULE] Rule for VM preservation: never, on-failure, always 18 | [Default: always] 19 | -r, --remote-workdir DIRECTORY Working directory on the remote host 20 | -s, --skipcheck Skip the "check" stage when building components 21 | -w, --workdir DIRECTORY Working directory on the local host 22 | -v, --verbose Only here for backwards compatibility. Does nothing. 23 | 24 | Engines: 25 | always_be_scheduling: default engine using Puppet's ABS infrastructure 26 | docker: a docker container on the local host 27 | ec2: an Amazon EC2 instance 28 | hardware: a dedicated hardware device 29 | local: the local machine, cannot be used with a target 30 | pooler: [deprecated] Puppet's vmpooler 31 | DOCOPT 32 | 33 | def parse(argv) 34 | Docopt.docopt(DOCUMENTATION, { argv: argv }) 35 | rescue Docopt::Exit => e 36 | VanagonLogger.error e.message 37 | exit 1 38 | end 39 | 40 | def run(options) # rubocop:disable Metrics/AbcSize 41 | project = options[:project_name] 42 | platform_list = options[:platforms].split(',') 43 | target_list = [] 44 | unless options[:targets].nil? || options[:targets].empty? 45 | target_list = options[:targets].split(',') 46 | end 47 | 48 | only_build = [] 49 | unless options[:only_build].nil? || options[:only_build].empty? 50 | only_build = options[:only_build].split(',') 51 | end 52 | 53 | platform_list.zip(target_list).each do |pair| 54 | platform, target = pair 55 | artifact = Vanagon::Driver.new(platform, project, options.merge({ :target => target, :only_build => only_build })) 56 | artifact.run 57 | end 58 | end 59 | 60 | def options_translate(docopt_options) 61 | translations = { 62 | '--verbose' => :verbose, 63 | '--workdir' => :workdir, 64 | '--remote-workdir' => :'remote-workdir', 65 | '--configdir' => :configdir, 66 | '--engine' => :engine, 67 | '--skipcheck' => :skipcheck, 68 | '--preserve' => :preserve, 69 | '--only-build' => :only_build, 70 | '' => :project_name, 71 | '' => :platforms, 72 | '' => :targets 73 | } 74 | return docopt_options.map { |k, v| [translations[k], v] }.to_h 75 | end 76 | 77 | def options_validate(options) 78 | # Handle --preserve option checking 79 | valid_preserves = %w[always never on-failure] 80 | unless valid_preserves.include? options[:preserve] 81 | raise InvalidArgument, "--preserve option can only be one of: #{valid_preserves.join(', ')}" 82 | end 83 | options[:preserve] = options[:preserve].to_sym 84 | return options 85 | end 86 | end 87 | end 88 | end 89 | -------------------------------------------------------------------------------- /lib/vanagon/cli/build_host_info.rb: -------------------------------------------------------------------------------- 1 | require 'docopt' 2 | require 'vanagon/logger' 3 | 4 | class Vanagon 5 | class CLI 6 | class BuildHostInfo < Vanagon::CLI 7 | DOCUMENTATION = <<~DOCOPT.freeze 8 | Usage: 9 | build_host_info [options] 10 | 11 | Options: 12 | -h, --help Display help 13 | -c, --configdir DIRECTORY Configuration directory [default: #{Dir.pwd}/configs] 14 | -e, --engine ENGINE Custom engine to use [default: always_be_scheduling] 15 | -w, --workdir DIRECTORY Working directory on the local host 16 | -v, --verbose Only here for backwards compatibility. Does nothing. 17 | 18 | Engines: 19 | always_be_scheduling: default engine using Puppet's ABS infrastructure 20 | docker: a docker container on the local host 21 | ec2: an Amazon EC2 instance 22 | hardware: a dedicated hardware device 23 | local: the local machine, cannot be used with a target 24 | pooler: [deprecated] Puppet's vmpooler 25 | DOCOPT 26 | 27 | def parse(argv) 28 | Docopt.docopt(DOCUMENTATION, { argv: argv }) 29 | rescue Docopt::Exit => e 30 | VanagonLogger.error e.message 31 | exit 1 32 | end 33 | 34 | def run(options) 35 | platforms = options[:platforms].split(',') 36 | project = options[:project_name] 37 | 38 | platforms.each do |platform| 39 | driver = Vanagon::Driver.new(platform, project, options) 40 | VanagonLogger.warn JSON.generate(driver.build_host_info) 41 | end 42 | end 43 | 44 | def options_translate(docopt_options) 45 | translations = { 46 | '--verbose' => :verbose, 47 | '--workdir' => :workdir, 48 | '--configdir' => :configdir, 49 | '--engine' => :engine, 50 | '' => :project_name, 51 | '' => :platforms, 52 | '' => :targets 53 | } 54 | return docopt_options.map { |k, v| [translations[k], v] }.to_h 55 | end 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /lib/vanagon/cli/build_requirements.rb: -------------------------------------------------------------------------------- 1 | require 'docopt' 2 | require 'json' 3 | require 'vanagon/logger' 4 | 5 | class Vanagon 6 | class CLI 7 | class BuildRequirements < Vanagon::CLI 8 | DOCUMENTATION = <<~DOCOPT.freeze 9 | Usage: 10 | build_requirements [options] 11 | 12 | Options: 13 | -h, --help Display help 14 | -c, --configdir DIRECTORY Configuration directory [default: #{Dir.pwd}/configs] 15 | -e, --engine ENGINE Custom engine to use [default: always_be_scheduling] 16 | -w, --workdir DIRECTORY Working directory on the local host 17 | -v, --verbose Only here for backwards compatibility. Does nothing. 18 | 19 | Engines: 20 | always_be_scheduling: default engine using Puppet's ABS infrastructure 21 | docker: a docker container on the local host 22 | ec2: an Amazon EC2 instance 23 | hardware: a dedicated hardware device 24 | local: the local machine, cannot be used with a target 25 | pooler: [deprecated] Puppet's vmpooler 26 | DOCOPT 27 | 28 | def parse(argv) 29 | Docopt.docopt(DOCUMENTATION, { argv: argv }) 30 | rescue Docopt::Exit => e 31 | VanagonLogger.error e.message 32 | exit 1 33 | end 34 | 35 | def run(options) # rubocop:disable Metrics/AbcSize 36 | platform = options[:platform] 37 | project = options[:project_name] 38 | driver = Vanagon::Driver.new(platform, project) 39 | 40 | components = driver.project.components 41 | component_names = components.map(&:name) 42 | build_requirements = [] 43 | components.each do |component| 44 | build_requirements << component.build_requires.reject do |requirement| 45 | # only include external requirements: i.e. those that do not match 46 | # other components in the project 47 | component_names.include?(requirement) 48 | end 49 | end 50 | 51 | VanagonLogger.warn "**** External packages required to build #{project} on #{platform}: ***" 52 | VanagonLogger.warn JSON.pretty_generate(build_requirements.flatten.uniq.sort) 53 | end 54 | 55 | def options_translate(docopt_options) 56 | translations = { 57 | '--verbose' => :verbose, 58 | '--workdir' => :workdir, 59 | '--configdir' => :configdir, 60 | '--engine' => :engine, 61 | '' => :project_name, 62 | '' => :platform, 63 | } 64 | return docopt_options.map { |k, v| [translations[k], v] }.to_h 65 | end 66 | end 67 | end 68 | end 69 | -------------------------------------------------------------------------------- /lib/vanagon/cli/completion.rb: -------------------------------------------------------------------------------- 1 | require 'docopt' 2 | require 'vanagon/logger' 3 | 4 | class Vanagon 5 | class CLI 6 | class Completion < Vanagon::CLI 7 | DOCUMENTATION = <<~DOCOPT.freeze 8 | Usage: 9 | completion [options] 10 | 11 | Options: 12 | -h, --help Display help 13 | -s, --shell SHELL Specify shell for completion script [default: bash] 14 | DOCOPT 15 | 16 | def parse(argv) 17 | Docopt.docopt(DOCUMENTATION, { argv: argv }) 18 | rescue Docopt::Exit => e 19 | VanagonLogger.error e.message 20 | exit 1 21 | end 22 | 23 | def run(options) 24 | shell = options[:shell].downcase.strip 25 | completion_file = File.expand_path(File.join('..', '..', '..', '..', 'extras', 'completions', "vanagon.#{shell}"), __FILE__) 26 | 27 | if File.exist?(completion_file) 28 | VanagonLogger.warn completion_file 29 | exit 0 30 | else 31 | VanagonLogger.error "Could not find completion file for '#{shell}': No such file #{completion_file}" 32 | exit 1 33 | end 34 | end 35 | 36 | def options_translate(docopt_options) 37 | translations = { 38 | '--shell' => :shell, 39 | } 40 | return docopt_options.map { |k, v| [translations[k], v] }.to_h 41 | end 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /lib/vanagon/cli/dependencies.rb: -------------------------------------------------------------------------------- 1 | require 'docopt' 2 | require 'json' 3 | require 'vanagon/logger' 4 | 5 | class Vanagon 6 | class CLI 7 | class Dependencies < Vanagon::CLI 8 | DOCUMENTATION = <<~DOCOPT.freeze 9 | Usage: 10 | dependencies [options] 11 | 12 | Options: 13 | -h, --help Display help 14 | -c, --configdir DIRECTORY Configuration directory [default: #{Dir.pwd}/configs] 15 | -w, --workdir DIRECTORY Working directory on the local host 16 | -v, --verbose Only here for backwards compatibility. Does nothing. 17 | 18 | Project-Name: 19 | May be a project name of a project from the configs/projects directory or 'all' to generate dependencies for all projects. 20 | Platforms: 21 | May be a platform name of a platform from the configs/platforms directory or 'all' to generate dependencies for all platforms. 22 | DOCOPT 23 | 24 | def parse(argv) 25 | Docopt.docopt(DOCUMENTATION, { argv: argv }) 26 | rescue Docopt::Exit => e 27 | VanagonLogger.error e.message 28 | exit 1 29 | end 30 | 31 | def run(options) 32 | projects = get_projects(options) 33 | platforms = get_platforms(options) 34 | failures = [] 35 | 36 | projects.each do |project| 37 | platforms.each do |platform| 38 | begin 39 | artifact = Vanagon::Driver.new(platform, project, options) 40 | artifact.dependencies 41 | rescue RuntimeError => e 42 | failures.push("#{project}, #{platform}: #{e}") 43 | end 44 | end 45 | end 46 | 47 | unless failures.empty? 48 | VanagonLogger.info "Failed to generate dependencies for the following:" 49 | failures.each do |failure| 50 | VanagonLogger.info failure 51 | end 52 | end 53 | 54 | VanagonLogger.info "Finished generating dependencies" 55 | end 56 | 57 | def get_projects(options) 58 | platforms_directory = File.join(options[:configdir], 'platforms') 59 | projects_directory = File.join(options[:configdir], 'projects') 60 | 61 | unless Dir.exist?(projects_directory) && Dir.exist?(platforms_directory) 62 | VanagonLogger.error "Path to #{platforms_directory} or #{projects_directory} not found." 63 | exit 1 64 | end 65 | 66 | projects = [options[:project_name]] 67 | if projects.include?('all') 68 | Dir.children(projects_directory).map do |project| 69 | File.basename(project, File.extname(project)) 70 | end 71 | else 72 | projects 73 | end 74 | end 75 | 76 | def get_platforms(options) 77 | platforms = options[:platforms].split(',') 78 | if platforms.include?('all') 79 | Dir.children(platforms_directory).map do |platform| 80 | File.basename(platform, File.extname(platform)) 81 | end 82 | else 83 | platforms 84 | end 85 | end 86 | 87 | def options_translate(docopt_options) 88 | translations = { 89 | '--verbose' => :verbose, 90 | '--workdir' => :workdir, 91 | '--configdir' => :configdir, 92 | '' => :project_name, 93 | '' => :platforms 94 | } 95 | return docopt_options.map { |k, v| [translations[k], v] }.to_h 96 | end 97 | end 98 | end 99 | end 100 | -------------------------------------------------------------------------------- /lib/vanagon/cli/inspect.rb: -------------------------------------------------------------------------------- 1 | require 'docopt' 2 | require 'json' 3 | require 'vanagon/logger' 4 | 5 | class Vanagon 6 | class CLI 7 | class Inspect < Vanagon::CLI 8 | DOCUMENTATION = <<~DOCOPT.freeze 9 | Usage: 10 | inspect [options] 11 | 12 | Options: 13 | -h, --help Display help 14 | -c, --configdir DIRECTORY Configuration directory [default: #{Dir.pwd}/configs] 15 | -e, --engine ENGINE Custom engine to use [default: always_be_scheduling] 16 | 17 | -p, --preserve [RULE] Rule for VM preservation: never, on-failure, always 18 | [Default: on-failure] 19 | -w, --workdir DIRECTORY Working directory on the local host 20 | -v, --verbose Only here for backwards compatibility. Does nothing. 21 | 22 | Engines: 23 | always_be_scheduling: default engine using Puppet's ABS infrastructure 24 | docker: a docker container on the local host 25 | ec2: an Amazon EC2 instance 26 | hardware: a dedicated hardware device 27 | local: the local machine, cannot be used with a target 28 | pooler: [deprecated] Puppet's vmpooler 29 | DOCOPT 30 | 31 | def parse(argv) 32 | Docopt.docopt(DOCUMENTATION, { argv: argv }) 33 | rescue Docopt::Exit => e 34 | VanagonLogger.error e.message 35 | exit 1 36 | end 37 | 38 | def run(options) 39 | platforms = options[:platforms].split(',') 40 | project = options[:project_name] 41 | 42 | platforms.each do |platform| 43 | driver = Vanagon::Driver.new(platform, project, options) 44 | components = driver.project.components.map(&:to_hash) 45 | VanagonLogger.warn JSON.pretty_generate(components) 46 | end 47 | end 48 | 49 | def options_translate(docopt_options) 50 | translations = { 51 | '--verbose' => :verbose, 52 | '--workdir' => :workdir, 53 | '--configdir' => :configdir, 54 | '--engine' => :engine, 55 | '--preserve' => :preserve, 56 | '' => :project_name, 57 | '' => :platforms 58 | } 59 | return docopt_options.map { |k, v| [translations[k], v] }.to_h 60 | end 61 | 62 | def options_validate(options) 63 | # Handle --preserve option checking 64 | valid_preserves = %w[always never on-failure] 65 | unless valid_preserves.include? options[:preserve] 66 | raise InvalidArgument, "--preserve option can only be one of: #{valid_preserves.join(', ')}" 67 | end 68 | options[:preserve] = options[:preserve].to_sym 69 | return options 70 | end 71 | end 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /lib/vanagon/cli/list.rb: -------------------------------------------------------------------------------- 1 | require 'docopt' 2 | require 'vanagon/logger' 3 | 4 | class Vanagon 5 | class CLI 6 | class List < Vanagon::CLI 7 | DOCUMENTATION = <<~DOCOPT.freeze 8 | Usage: 9 | list [options] 10 | 11 | Options: 12 | -h, --help Display help 13 | -c, --configdir DIRECTORY Configuration directory [default: #{Dir.pwd}/configs] 14 | -d, --defaults Display the list of default platforms 15 | -l, --platforms Display a list of platforms 16 | -r, --projects Display a list of projects 17 | -s, --use-spaces Displays the list as space separated 18 | DOCOPT 19 | 20 | def parse(argv) 21 | Docopt.docopt(DOCUMENTATION, { argv: argv }) 22 | rescue Docopt::Exit => e 23 | VanagonLogger.error e.message 24 | exit 1 25 | end 26 | 27 | def output(list, use_spaces) 28 | return list.join(' ') if use_spaces 29 | return list 30 | end 31 | 32 | def run(options) # rubocop:disable Metrics/AbcSize 33 | check_directories(options) 34 | 35 | default_list = topic_list(File.dirname(__FILE__), '..', 'platform', 'defaults') 36 | platform_list = topic_list(options[:configdir], 'platforms') 37 | project_list = topic_list(options[:configdir], 'projects') 38 | 39 | if options[:defaults] 40 | puts "- Defaults", output(default_list, options[:use_spaces]) 41 | return 42 | end 43 | 44 | if options[:projects] == options[:platforms] 45 | puts "- Projects", output(project_list, options[:use_spaces]), "\n", 46 | "- Platforms", output(platform_list, options[:use_spaces]) 47 | return 48 | end 49 | 50 | if options[:projects] 51 | puts "- Projects", output(project_list, options[:use_spaces]) 52 | return 53 | end 54 | 55 | if options[:platforms] 56 | puts "- Platforms", output(platform_list, options[:use_spaces]) 57 | return 58 | end 59 | end 60 | 61 | def check_directories(options) 62 | platforms_directory = File.join(options[:configdir], 'platforms') 63 | projects_directory = File.join(options[:configdir], 'projects') 64 | 65 | unless Dir.exist?(platforms_directory) 66 | VanagonLogger.error "Platforms directory \"#{platforms_directory}\" does not exist." 67 | exit 1 68 | end 69 | 70 | unless Dir.exist?(projects_directory) 71 | VanagonLogger.error "Projectss directory \"#{projects_directory}\" does not exist." 72 | exit 1 73 | end 74 | end 75 | 76 | def topic_list(*topic_path_items) 77 | Dir.children(File.join(topic_path_items)).map do |t| 78 | File.basename(t, File.extname(t)) 79 | end.sort 80 | end 81 | 82 | def options_translate(docopt_options) 83 | translations = { 84 | '--configdir' => :configdir, 85 | '--defaults' => :defaults, 86 | '--platforms' => :platforms, 87 | '--projects' => :projects, 88 | '--use-spaces' => :use_spaces, 89 | } 90 | return docopt_options.map { |k, v| [translations[k], v] }.to_h 91 | end 92 | end 93 | end 94 | end 95 | -------------------------------------------------------------------------------- /lib/vanagon/cli/render.rb: -------------------------------------------------------------------------------- 1 | require 'docopt' 2 | require 'json' 3 | require 'vanagon/logger' 4 | 5 | class Vanagon 6 | class CLI 7 | class Render < Vanagon::CLI 8 | DOCUMENTATION = <<~DOCOPT.freeze 9 | Usage: 10 | render [options] 11 | 12 | Options: 13 | -h, --help Display help 14 | -c, --configdir DIRECTORY Configuration directory [default: #{Dir.pwd}/configs] 15 | -e, --engine ENGINE Custom engine to use [default: always_be_scheduling] 16 | -w, --workdir DIRECTORY Working directory on the local host 17 | -v, --verbose Only here for backwards compatibility. Does nothing. 18 | 19 | Engines: 20 | always_be_scheduling: default engine using Puppet's ABS infrastructure 21 | docker: a docker container on the local host 22 | ec2: an Amazon EC2 instance 23 | hardware: a dedicated hardware device 24 | local: the local machine, cannot be used with a target 25 | pooler: [deprecated] Puppet's vmpooler 26 | DOCOPT 27 | 28 | def parse(argv) 29 | Docopt.docopt(DOCUMENTATION, { argv: argv }) 30 | rescue Docopt::Exit => e 31 | VanagonLogger.error e.message 32 | exit 1 33 | end 34 | 35 | def run(options) 36 | platforms = options[:platforms].split(',') 37 | project = options[:project_name] 38 | target_list = [] 39 | 40 | platforms.zip(target_list).each do |pair| 41 | platform, target = pair 42 | artifact = Vanagon::Driver.new(platform, project, options.merge({ :target => target })) 43 | artifact.render 44 | end 45 | end 46 | 47 | def options_translate(docopt_options) 48 | translations = { 49 | '--verbose' => :verbose, 50 | '--workdir' => :workdir, 51 | '--configdir' => :configdir, 52 | '--engine' => :engine, 53 | '' => :project_name, 54 | '' => :platforms, 55 | } 56 | return docopt_options.map { |k, v| [translations[k], v] }.to_h 57 | end 58 | end 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /lib/vanagon/cli/ship.rb: -------------------------------------------------------------------------------- 1 | require 'docopt' 2 | require 'vanagon/logger' 3 | 4 | class Vanagon 5 | class CLI 6 | class Ship < Vanagon::CLI 7 | DOCUMENTATION = <<~DOCOPT.freeze 8 | Usage: 9 | ship [--help] 10 | 11 | Options: 12 | -h, --help Display help 13 | DOCOPT 14 | 15 | def parse(argv) 16 | Docopt.docopt(DOCUMENTATION, { argv: argv }) 17 | rescue Docopt::Exit => e 18 | VanagonLogger.error e.message 19 | exit 1 20 | end 21 | 22 | def run(_) 23 | ENV['PROJECT_ROOT'] = Dir.pwd 24 | 25 | if Dir['output/**/*'].select { |entry| File.file?(entry) }.empty? 26 | VanagonLogger.error 'vanagon: Error: No packages to ship in the "output" directory. Maybe build some first?' 27 | exit 1 28 | end 29 | 30 | require 'packaging' 31 | Pkg::Util::RakeUtils.load_packaging_tasks 32 | Pkg::Util::RakeUtils.invoke_task('pl:jenkins:ship', 'artifacts', 'output') 33 | Pkg::Util::RakeUtils.invoke_task('pl:jenkins:ship_to_artifactory', 'output') 34 | end 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/vanagon/cli/sign.rb: -------------------------------------------------------------------------------- 1 | require 'docopt' 2 | require 'vanagon/logger' 3 | 4 | class Vanagon 5 | class CLI 6 | class Sign < Vanagon::CLI 7 | DOCUMENTATION = <<~DOCOPT.freeze 8 | Usage: 9 | sign [--help] 10 | 11 | Options: 12 | -h, --help Display help 13 | DOCOPT 14 | 15 | def parse(argv) 16 | Docopt.docopt(DOCUMENTATION, { argv: argv }) 17 | rescue Docopt::Exit => e 18 | VanagonLogger.error e.message 19 | exit 1 20 | end 21 | 22 | def run(_) 23 | ENV['PROJECT_ROOT'] = Dir.pwd 24 | if Dir['output/**/*'].select { |entry| File.file?(entry) }.empty? 25 | VanagonLogger.error 'sign: Error: No packages to sign in the "output" directory. Maybe build some first?' 26 | exit 1 27 | end 28 | 29 | require 'packaging' 30 | Pkg::Util::RakeUtils.load_packaging_tasks 31 | Pkg::Util::RakeUtils.invoke_task('pl:jenkins:sign_all', 'output') 32 | end 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /lib/vanagon/common.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/common/pathname' 2 | require 'vanagon/common/user' 3 | -------------------------------------------------------------------------------- /lib/vanagon/common/user.rb: -------------------------------------------------------------------------------- 1 | class Vanagon 2 | class Common 3 | class User 4 | attr_accessor :name, :group, :shell, :is_system, :homedir 5 | 6 | def initialize(name, group = nil, shell = nil, is_system = false, homedir = nil) 7 | @name = name 8 | @group = group ? group : @name 9 | @shell = shell if shell 10 | @is_system = is_system if is_system 11 | @homedir = homedir if homedir 12 | end 13 | 14 | # Equality. How does it even work? 15 | # 16 | # @return [true, false] true if all attributes have equal values. false otherwise. 17 | def ==(other) 18 | other.name == self.name && \ 19 | other.group == self.group && \ 20 | other.shell == self.shell && \ 21 | other.is_system == self.is_system && \ 22 | other.homedir == self.homedir 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/vanagon/component/source.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/logger' 2 | require 'vanagon/component/source/http' 3 | require 'vanagon/component/source/git' 4 | require 'vanagon/component/source/local' 5 | require 'vanagon/errors' 6 | 7 | class Vanagon 8 | class InvalidSource < Vanagon::Error 9 | end 10 | class Component 11 | class Source 12 | SUPPORTED_PROTOCOLS = %w[file http https git].freeze 13 | 14 | class << self 15 | # Factory to hand back the correct {Vanagon::Component::Source} subtype to the component 16 | # 17 | # @param uri_instance [#to_s] URI of the source file (includes git@... style links) 18 | # @param options [Hash] hash of the options needed for the subtype 19 | # @param workdir [String] working directory to fetch the source into 20 | # @return [Vanagon::Component::Source] the correct subtype for the given source 21 | def source(uri_instance, **options) # rubocop:disable Metrics/AbcSize 22 | # Sometimes the uri comes in as a string, but sometimes it's already been 23 | # coerced into a URI object. The individual source providers will turn 24 | # the passed uri into a URI object if needed, but for this method we 25 | # want to work with the uri as a string. 26 | uri = uri_instance.to_s 27 | if uri.start_with?('git') 28 | source_type = :git 29 | # when using an http(s) source for a git repo, you should prefix the 30 | # url with `git:`, so something like `git:https://github.com/puppetlabs/vanagon` 31 | # strip the leading `git:` so we have a valid uri 32 | uri.sub!(/^git:http/, 'http') 33 | else 34 | source_type = determine_source_type(uri) 35 | end 36 | 37 | if source_type == :git 38 | return Vanagon::Component::Source::Git.new uri, 39 | sum: options[:sum], 40 | ref: options[:ref], 41 | workdir: options[:workdir], 42 | dirname: options[:dirname], 43 | clone_options: options[:clone_options] 44 | end 45 | 46 | if source_type == :http 47 | return Vanagon::Component::Source::Http.new uri, 48 | sum: options[:sum], 49 | workdir: options[:workdir], 50 | # Default sum_type is md5 if unspecified: 51 | sum_type: options[:sum_type] || "md5" 52 | end 53 | 54 | if source_type == :local 55 | return Vanagon::Component::Source::Local.new uri, 56 | workdir: options[:workdir] 57 | end 58 | 59 | # Unknown source type! 60 | raise Vanagon::InvalidSource, 61 | "Source is invalid or of an unknown type: '#{uri}'; cannot continue" 62 | end 63 | 64 | def determine_source_type(uri) 65 | # if source_type isn't specified, let's try to figure out what we have 66 | # order of precedence for this is git, then http, then local 67 | 68 | # Add a 5 second timeout for the `git remote-ls` execution to deal with 69 | # URLs that incorrectly respond to git queries 70 | timeout = 5 71 | if Vanagon::Component::Source::Git.valid_remote?(uri, timeout) 72 | if uri =~ /^http/ 73 | VanagonLogger.warn "Using http(s) URIs for github is deprecated. " \ 74 | "Use `git:` URI scheme instead." 75 | end 76 | return :git 77 | end 78 | 79 | if Vanagon::Component::Source::Http.valid_url?(uri) 80 | return :http 81 | end 82 | 83 | if Vanagon::Component::Source::Local.valid_file?(uri) 84 | return :local 85 | end 86 | 87 | return :unknown 88 | end 89 | end 90 | end 91 | end 92 | end 93 | -------------------------------------------------------------------------------- /lib/vanagon/engine/ec2.rb: -------------------------------------------------------------------------------- 1 | require 'aws-sdk' 2 | require 'erb' 3 | require 'base64' 4 | require 'vanagon/engine/base' 5 | require 'vanagon/logger' 6 | 7 | class Vanagon 8 | class Engine 9 | class Ec2 < Base 10 | attr_accessor :ami, :key_name, :userdata, :key, :shutdown_behavior 11 | attr_accessor :subnet_id, :instance_type 12 | 13 | def initialize(platform, target = nil, **opts) 14 | super 15 | 16 | @ami = @platform.aws_ami 17 | @target_user = @platform.target_user 18 | @subnet_id = @platform.aws_subnet_id 19 | @userdata = @platform.aws_user_data 20 | @region = @platform.aws_region || 'us-east-1' 21 | @key_name = @platform.aws_key_name 22 | @key = @platform.aws_key 23 | @instance_type = @platform.aws_instance_type || "t1.micro" 24 | @required_attributes = ["ssh_port", "aws_ami", "aws_key_name"] 25 | @shutdown_behavior = @platform.aws_shutdown_behavior 26 | 27 | @ec2 = ::Aws::EC2::Client.new(region: @region) 28 | @resource = ::Aws::EC2::Resource.new(client: @ec2) 29 | end 30 | 31 | def name 32 | 'ec2' 33 | end 34 | 35 | def get_userdata 36 | unless @userdata.nil? 37 | Base64.encode64(ERB.new(@userdata).result(binding)) 38 | end 39 | end 40 | 41 | def instances 42 | @instances ||= @resource.create_instances({ 43 | image_id: ami, 44 | min_count: 1, 45 | max_count: 1, 46 | key_name: key_name, 47 | instance_type: instance_type, 48 | subnet_id: subnet_id, 49 | user_data: get_userdata, 50 | monitoring: { 51 | enabled: false, 52 | } 53 | }) 54 | end 55 | 56 | def instance 57 | @instance ||= instances.first 58 | end 59 | 60 | def select_target 61 | VanagonLogger.info "Instance created id: #{instance.id}" 62 | VanagonLogger.info "Created instance waiting for status ok" 63 | @ec2.wait_until(:instance_status_ok, instance_ids: [instance.id]) 64 | VanagonLogger.info "Instance running" 65 | @target = instance.private_ip_address 66 | rescue ::Aws::Waiters::Errors::WaiterFailed => error 67 | fail "Failed to wait for ec2 instance to start got error #{error}" 68 | end 69 | 70 | def teardown 71 | VanagonLogger.info "Destroying instance on AWS id: #{instance.id}" 72 | instances.batch_terminate! 73 | end 74 | end 75 | end 76 | end 77 | -------------------------------------------------------------------------------- /lib/vanagon/engine/hardware.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/engine/base' 2 | require 'vanagon/logger' 3 | require 'json' 4 | require 'lock_manager' 5 | 6 | LOCK_MANAGER_HOST = ENV['LOCK_MANAGER_HOST'] || 'redis' 7 | LOCK_MANAGER_PORT = ENV['LOCK_MANAGER_PORT'] || 6379 8 | VANAGON_LOCK_USER = ENV['USER'] 9 | 10 | 11 | class Vanagon 12 | class Engine 13 | # Class to use when building on a hardware device (e.g. AIX, Switch, etc) 14 | # 15 | class Hardware < Base 16 | # This method is used to obtain a vm to build upon 17 | # For the base class we just return the target that was passed in 18 | def select_target 19 | @target = node_lock(@build_hosts) 20 | end 21 | 22 | # Poll for a lock 23 | def polling_lock(host) 24 | Vanagon::Driver.logger.info "Polling for a lock on #{host}." 25 | @lockman.polling_lock(host, VANAGON_LOCK_USER, "Vanagon automated lock") 26 | Vanagon::Driver.logger.info "Lock acquired on #{host}." 27 | VanagonLogger.info "Lock acquired on #{host} for #{VANAGON_LOCK_USER}." 28 | host 29 | end 30 | 31 | # Iterate over the options and find a node open to lock. 32 | def node_lock(hosts) 33 | hosts.each do |h| 34 | Vanagon::Driver.logger.info "Attempting to lock #{h}." 35 | if @lockman.lock(h, VANAGON_LOCK_USER, "Vanagon automated lock") 36 | Vanagon::Driver.logger.info "Lock acquired on #{h}." 37 | VanagonLogger.info "Lock acquired on #{h} for #{VANAGON_LOCK_USER}." 38 | return h 39 | end 40 | end 41 | # If they are all locked, fall back to a polling lock on last item 42 | polling_lock(hosts.pop) 43 | end 44 | 45 | # Steps needed to tear down or clean up the system after the build is 46 | # complete. In this case, we'll attempt to unlock the hardware 47 | def teardown 48 | Vanagon::Driver.logger.info "Removing lock on #{@target}." 49 | VanagonLogger.info "Removing lock on #{@target}." 50 | @lockman.unlock(@target, VANAGON_LOCK_USER) 51 | end 52 | 53 | def initialize(platform, target, **opts) 54 | super 55 | 56 | Vanagon::Driver.logger.debug "Hardware engine invoked." 57 | @build_hosts = platform.build_hosts 58 | # Redis is the only backend supported in lock_manager currently 59 | @lockman = LockManager.new(type: 'redis', server: LOCK_MANAGER_HOST) 60 | @required_attributes << "build_hosts" 61 | end 62 | 63 | # Get the engine name 64 | def name 65 | 'hardware' 66 | end 67 | 68 | # Get the first build host name to build on 69 | def build_host_name 70 | if @build_host_name.nil? 71 | validate_platform 72 | # For now, get the first build host. In the future, lock management 73 | # will be pushed into the pooler (or something that wraps it), and 74 | # the hardware engine can go away. 75 | @build_host_name = @build_hosts.first 76 | end 77 | 78 | @build_host_name 79 | end 80 | end 81 | end 82 | end 83 | -------------------------------------------------------------------------------- /lib/vanagon/engine/local.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/engine/base' 2 | require 'vanagon/utilities' 3 | require 'vanagon/errors' 4 | 5 | class Vanagon 6 | class Engine 7 | class Local < Base 8 | def initialize(platform, target = nil, **opts) 9 | # local engine can't be used with a target 10 | super(platform, 'local machine') 11 | 12 | # We inherit a set of required attributes from Base, 13 | # and rather than instantiate a new empty array for 14 | # required attributes, we can just clear out the 15 | # existing ones. 16 | @required_attributes.clear 17 | end 18 | 19 | # Get the engine name 20 | def name 21 | 'local' 22 | end 23 | 24 | # Return the target name to build on 25 | def build_host_name 26 | if @build_host_name.nil? 27 | validate_platform 28 | @build_host_name = @target 29 | end 30 | 31 | @build_host_name 32 | end 33 | 34 | # Dispatches the command for execution 35 | def dispatch(command, return_output = false) 36 | Vanagon::Utilities.local_command(command, return_command_output: return_output) 37 | end 38 | 39 | def ship_workdir(workdir) 40 | FileUtils.cp_r(Dir.glob("#{workdir}/*"), @remote_workdir) 41 | end 42 | 43 | def retrieve_built_artifact(artifacts_to_fetch, no_packaging) 44 | output_path = 'output/' 45 | FileUtils.mkdir_p(output_path) 46 | unless no_packaging 47 | artifacts_to_fetch << "#{@remote_workdir}/output/*" 48 | end 49 | artifacts_to_fetch.each do |path| 50 | FileUtils.cp_r(Dir.glob(path), "output/") 51 | end 52 | end 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /lib/vanagon/errors.rb: -------------------------------------------------------------------------------- 1 | class Vanagon 2 | # An error class that accepts a wrapped error message 3 | # 4 | class Error < StandardError 5 | attr_accessor :original 6 | 7 | # Generate a wrapped exception 8 | # 9 | # @param original [Exception] The exception to wrap 10 | # @param mesg [String] 11 | # 12 | # @return [Vanagon::Error] 13 | def self.wrap(original, mesg) 14 | new(mesg).tap do |e| 15 | e.set_backtrace(caller(4)) 16 | e.original = original 17 | end 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/vanagon/extensions/hashable.rb: -------------------------------------------------------------------------------- 1 | # This is bad, and I feel bad. This will let you append 2 | # broadly useful Hash and JSON casting on any class that 3 | # includes it. But it's pretty naive, in that it just turns 4 | # attributes names into keys while retaining their 5 | # associated values. 6 | module HashableAttributes 7 | # @return [Hash] Converts an object to a hash with keys representing 8 | # each attribute (as symbols) and their corresponding values 9 | def to_hash 10 | instance_variables.each_with_object({}) do |var, hash| 11 | hash[var.to_s.delete("@")] = instance_variable_get(var) 12 | end 13 | end 14 | alias_method :to_h, :to_hash 15 | 16 | def to_json(*options) 17 | to_hash.to_json options 18 | end 19 | end 20 | 21 | class Vanagon 22 | # Vanagon classes generally don't implement JSON or Hash functionality 23 | # so those need to be monkey-patched for useful inspection. 24 | 25 | class Platform 26 | include HashableAttributes 27 | end 28 | 29 | class Common 30 | class Pathname 31 | include HashableAttributes 32 | end 33 | end 34 | 35 | class Component 36 | include HashableAttributes 37 | end 38 | 39 | class Patch 40 | include HashableAttributes 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/vanagon/extensions/ostruct/json.rb: -------------------------------------------------------------------------------- 1 | require 'ostruct' 2 | require 'json' 3 | 4 | module OpenStructJson 5 | def to_json(*options) 6 | to_h.to_json options 7 | end 8 | end 9 | 10 | class OpenStruct 11 | prepend OpenStructJson 12 | end 13 | -------------------------------------------------------------------------------- /lib/vanagon/extensions/set/json.rb: -------------------------------------------------------------------------------- 1 | require 'set' 2 | require 'json' 3 | 4 | module SetJson 5 | def to_json(*options) 6 | to_a.to_json(*options) 7 | end 8 | end 9 | 10 | class Set 11 | prepend SetJson 12 | end 13 | -------------------------------------------------------------------------------- /lib/vanagon/extensions/string.rb: -------------------------------------------------------------------------------- 1 | # String is generally pretty functional, but sometimes you need 2 | # a couple of small convienence methods to make working with really 3 | # long or really funky strings easier. This will indent all lines 4 | # to the margin of the first line, preserving sunsequent indentation 5 | # while still helping reign in HEREDOCS. 6 | class String 7 | # @return [String] 8 | def undent 9 | gsub(/^.{#{slice(/^\s+/).length}}/, '') 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/vanagon/logger.rb: -------------------------------------------------------------------------------- 1 | require 'logger' 2 | 3 | class VanagonLogger < Logger 4 | def self.logger 5 | @@logger ||= VanagonLogger.new 6 | end 7 | 8 | def self.debug_logger 9 | @@debug_logger ||= VanagonLogger.new($stderr) 10 | end 11 | 12 | def self.info(msg) 13 | VanagonLogger.debug_logger.info msg 14 | end 15 | 16 | def self.warn(msg) 17 | VanagonLogger.logger.warn msg 18 | end 19 | 20 | def self.error(msg) 21 | VanagonLogger.logger.error msg 22 | end 23 | 24 | def initialize(output = $stdout) 25 | super(output) 26 | self.level = ::Logger::INFO 27 | self.formatter = proc do |severity, datetime, progname, msg| 28 | "#{msg}\n" 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /lib/vanagon/patch.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/errors' 2 | 3 | class Vanagon 4 | class Patch 5 | # @!attribute [r] origin_path 6 | # @return [String] The path to the patch before assembly 7 | attr_reader :origin_path 8 | 9 | # @!attribute [r] namespace 10 | # @return [String] The namespace for the patch 11 | attr_reader :namespace 12 | 13 | # @!attribute [r] assembly_path 14 | # @return [String] The path to the patch inside the assembly 15 | attr_reader :assembly_path 16 | 17 | # @!attribute [r] destination 18 | # @return [String] The working directory where this patch will be applied. 19 | # Only used for post-installation patches. 20 | attr_reader :destination 21 | 22 | # @!attribute [r] strip 23 | # @return [Integer] the number of path components to strip from the patch path 24 | attr_reader :strip 25 | 26 | # @!attribute [r] fuzz 27 | # @return [Integer] The fuzz factor for applying the patch 28 | attr_reader :fuzz 29 | 30 | # @!attribute [r] after 31 | # @return [String] What step should this patch be applied to, one of ["unpack", "install"] 32 | attr_reader :after 33 | 34 | def initialize(origin_path, component, options) # rubocop:disable Metrics/AbcSize,Metrics/PerceivedComplexity 35 | valid_keys = %i[namespace destination strip fuzz after] 36 | bad_keys = options.each_key.reject { |k| valid_keys.include? k } 37 | 38 | unless bad_keys.empty? 39 | raise Vanagon::Error, "Bad options in patch initialization: #{bad_keys}." 40 | end 41 | 42 | @origin_path = origin_path 43 | @namespace = options[:namespace] || component.name 44 | @assembly_path = "patches/#{@namespace}/#{File.basename(@origin_path)}" 45 | @strip = options[:strip] || 1 46 | @fuzz = options[:fuzz] || 0 47 | @after = options[:after] || 'unpack' 48 | unless ['unpack', 'install'].include?(@after) 49 | raise Vanagon::Error, 'Only "unpack" or "install" permitted for "after" option.' 50 | end 51 | @destination = options[:destination] || component.dirname 52 | end 53 | 54 | def cmd(platform) 55 | return "#{platform.patch} --strip=#{@strip} --fuzz=#{@fuzz} --ignore-whitespace --no-backup-if-mismatch < $(workdir)/#{@assembly_path}" 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/amazon-2-aarch64.rb: -------------------------------------------------------------------------------- 1 | platform "amazon-2-aarch64" do |plat| 2 | plat.servicedir "/usr/lib/systemd/system" 3 | plat.defaultdir "/etc/sysconfig" 4 | plat.servicetype "systemd" 5 | 6 | packages = %w(autoconf automake createrepo gcc gcc-c++ rsync cmake3 make rpm-libs rpm-build libarchive) 7 | plat.provision_with("yum install -y --nogpgcheck #{packages.join(' ')}") 8 | plat.install_build_dependencies_with "yum install --assumeyes" 9 | plat.vmpooler_template "amazon-7-arm64" 10 | end 11 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/amazon-2023-aarch64.rb: -------------------------------------------------------------------------------- 1 | platform "amazon-2023-aarch64" do |plat| 2 | plat.servicedir "/usr/lib/systemd/system" 3 | plat.defaultdir "/etc/sysconfig" 4 | plat.servicetype "systemd" 5 | 6 | packages = %w(autoconf automake createrepo gcc gcc-c++ rsync cmake make rpm-libs rpm-build libarchive) 7 | plat.provision_with "dnf install -y --allowerasing #{packages.join(' ')}" 8 | plat.install_build_dependencies_with "dnf install -y --allowerasing " 9 | plat.vmpooler_template "amazon-2023-arm64" 10 | end 11 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/amazon-2023-x86_64.rb: -------------------------------------------------------------------------------- 1 | platform "amazon-2023-x86_64" do |plat| 2 | plat.servicedir "/usr/lib/systemd/system" 3 | plat.defaultdir "/etc/sysconfig" 4 | plat.servicetype "systemd" 5 | 6 | packages = %w(gcc gcc-c++ autoconf automake createrepo rsync cmake make rpm-libs rpm-build rpm-sign libtool libarchive) 7 | plat.provision_with "dnf install -y --allowerasing #{packages.join(' ')}" 8 | plat.install_build_dependencies_with "dnf install -y --allowerasing " 9 | plat.vmpooler_template "amazon-2023-x86_64" 10 | end 11 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/amazon-7-aarch64.rb: -------------------------------------------------------------------------------- 1 | platform "amazon-7-aarch64" do |plat| 2 | plat.servicedir "/usr/lib/systemd/system" 3 | plat.defaultdir "/etc/sysconfig" 4 | plat.servicetype "systemd" 5 | 6 | packages = %w(autoconf automake createrepo gcc gcc-c++ rsync cmake3 make rpm-libs rpm-build libarchive) 7 | plat.provision_with("yum install -y --nogpgcheck #{packages.join(' ')}") 8 | plat.install_build_dependencies_with "yum install --assumeyes" 9 | plat.vmpooler_template "amazon-7-arm64" 10 | end 11 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/debian-10-amd64.rb: -------------------------------------------------------------------------------- 1 | platform "debian-10-amd64" do |plat| 2 | plat.servicedir "/lib/systemd/system" 3 | plat.defaultdir "/etc/default" 4 | plat.servicetype "systemd" 5 | plat.codename "buster" 6 | 7 | packages = %w(build-essential devscripts make quilt pkg-config debhelper rsync fakeroot cmake) 8 | plat.provision_with "export DEBIAN_FRONTEND=noninteractive; apt-get update -qq; apt-get install -qy --no-install-recommends #{packages.join(' ')}" 9 | plat.install_build_dependencies_with "DEBIAN_FRONTEND=noninteractive; apt-get install -qy --no-install-recommends " 10 | plat.vmpooler_template "debian-10-x86_64" 11 | end 12 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/debian-11-aarch64.rb: -------------------------------------------------------------------------------- 1 | platform "debian-11-aarch64" do |plat| 2 | plat.servicedir "/lib/systemd/system" 3 | plat.defaultdir "/etc/default" 4 | plat.servicetype "systemd" 5 | plat.codename "bullseye" 6 | 7 | packages = %w(build-essential devscripts make quilt pkg-config debhelper rsync fakeroot cmake) 8 | plat.provision_with "export DEBIAN_FRONTEND=noninteractive; apt-get update -qq; apt-get install -qy --no-install-recommends #{packages.join(' ')}" 9 | plat.install_build_dependencies_with "DEBIAN_FRONTEND=noninteractive; apt-get install -qy --no-install-recommends " 10 | plat.vmpooler_template "debian-11-arm64" 11 | end 12 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/debian-11-amd64.rb: -------------------------------------------------------------------------------- 1 | platform "debian-11-amd64" do |plat| 2 | plat.servicedir "/lib/systemd/system" 3 | plat.defaultdir "/etc/default" 4 | plat.servicetype "systemd" 5 | plat.codename "bullseye" 6 | 7 | packages = %w(build-essential devscripts make quilt pkg-config debhelper rsync fakeroot cmake) 8 | plat.provision_with "export DEBIAN_FRONTEND=noninteractive; apt-get update -qq; apt-get install -qy --no-install-recommends #{packages.join(' ')}" 9 | plat.install_build_dependencies_with "DEBIAN_FRONTEND=noninteractive; apt-get install -qy --no-install-recommends " 10 | plat.vmpooler_template "debian-11-x86_64" 11 | end 12 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/debian-12-aarch64.rb: -------------------------------------------------------------------------------- 1 | platform "debian-12-aarch64" do |plat| 2 | plat.servicedir "/lib/systemd/system" 3 | plat.defaultdir "/etc/default" 4 | plat.servicetype "systemd" 5 | plat.codename "bookworm" 6 | 7 | packages = %w(build-essential devscripts make quilt pkg-config debhelper rsync fakeroot cmake) 8 | plat.provision_with "export DEBIAN_FRONTEND=noninteractive; apt-get update -qq; apt-get install -qy --no-install-recommends #{packages.join(' ')}" 9 | plat.install_build_dependencies_with "DEBIAN_FRONTEND=noninteractive; apt-get install -qy --no-install-recommends " 10 | plat.vmpooler_template "debian-12-arm64" 11 | end 12 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/debian-12-amd64.rb: -------------------------------------------------------------------------------- 1 | platform "debian-12-amd64" do |plat| 2 | plat.servicedir "/lib/systemd/system" 3 | plat.defaultdir "/etc/default" 4 | plat.servicetype "systemd" 5 | plat.codename "bookworm" 6 | 7 | packages = %w(build-essential devscripts make quilt pkg-config debhelper rsync fakeroot cmake) 8 | plat.provision_with "export DEBIAN_FRONTEND=noninteractive; apt-get update -qq; apt-get install -qy --no-install-recommends #{packages.join(' ')}" 9 | plat.install_build_dependencies_with "DEBIAN_FRONTEND=noninteractive; apt-get install -qy --no-install-recommends " 10 | plat.vmpooler_template "debian-12-x86_64" 11 | end 12 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/debian-8-amd64.rb: -------------------------------------------------------------------------------- 1 | platform "debian-8-amd64" do |plat| 2 | plat.servicedir "/lib/systemd/system" 3 | plat.defaultdir "/etc/default" 4 | plat.servicetype "systemd" 5 | plat.codename "jessie" 6 | 7 | plat.add_build_repository "http://pl-build-tools.delivery.puppetlabs.net/debian/pl-build-tools-release-#{plat.get_codename}.deb" 8 | packages = %w(build-essential devscripts make quilt pkg-config debhelper rsync fakeroot) 9 | plat.provision_with "export DEBIAN_FRONTEND=noninteractive; apt-get update -qq; apt-get install -qy --no-install-recommends #{packages.join(' ')}" 10 | plat.install_build_dependencies_with "DEBIAN_FRONTEND=noninteractive; apt-get install -qy --no-install-recommends " 11 | plat.vmpooler_template "debian-8-x86_64" 12 | end 13 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/debian-8-i386.rb: -------------------------------------------------------------------------------- 1 | platform "debian-8-i386" do |plat| 2 | plat.servicedir "/lib/systemd/system" 3 | plat.defaultdir "/etc/default" 4 | plat.servicetype "systemd" 5 | plat.codename "jessie" 6 | 7 | plat.add_build_repository "http://pl-build-tools.delivery.puppetlabs.net/debian/pl-build-tools-release-#{plat.get_codename}.deb" 8 | packages = %w(build-essential devscripts make quilt pkg-config debhelper rsync fakeroot) 9 | plat.provision_with "export DEBIAN_FRONTEND=noninteractive; apt-get update -qq; apt-get install -qy --no-install-recommends #{packages.join(' ')}" 10 | plat.install_build_dependencies_with "DEBIAN_FRONTEND=noninteractive; apt-get install -qy --no-install-recommends" 11 | plat.vmpooler_template "debian-8-i386" 12 | end 13 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/el-6-i386.rb: -------------------------------------------------------------------------------- 1 | platform "el-6-i386" do |plat| 2 | plat.servicedir "/etc/rc.d/init.d" 3 | plat.defaultdir "/etc/sysconfig" 4 | plat.servicetype "sysv" 5 | 6 | plat.add_build_repository "http://pl-build-tools.delivery.puppetlabs.net/yum/pl-build-tools-release-#{plat.get_os_name}-#{plat.get_os_version}.noarch.rpm" 7 | packages = %w(autoconf automake createrepo rsync gcc make rpmdevtools rpm-libs yum-utils rpm-sign) 8 | plat.provision_with "yum install --assumeyes #{packages.join(' ')}" 9 | plat.install_build_dependencies_with "yum install --assumeyes" 10 | plat.vmpooler_template "redhat-6-i386" 11 | end 12 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/el-6-x86_64.rb: -------------------------------------------------------------------------------- 1 | platform "el-6-x86_64" do |plat| 2 | plat.servicedir "/etc/rc.d/init.d" 3 | plat.defaultdir "/etc/sysconfig" 4 | plat.servicetype "sysv" 5 | 6 | plat.add_build_repository "http://pl-build-tools.delivery.puppetlabs.net/yum/pl-build-tools-release-#{plat.get_os_name}-#{plat.get_os_version}.noarch.rpm" 7 | packages = %w(autoconf automake createrepo rsync gcc make rpmdevtools rpm-libs yum-utils rpm-sign) 8 | plat.provision_with "yum install --assumeyes #{packages.join(' ')}" 9 | plat.install_build_dependencies_with "yum install --assumeyes" 10 | plat.vmpooler_template "redhat-6-x86_64" 11 | end 12 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/el-7-x86_64.rb: -------------------------------------------------------------------------------- 1 | platform "el-7-x86_64" do |plat| 2 | plat.servicedir "/usr/lib/systemd/system" 3 | plat.defaultdir "/etc/sysconfig" 4 | plat.servicetype "systemd" 5 | 6 | plat.add_build_repository "http://pl-build-tools.delivery.puppetlabs.net/yum/pl-build-tools-release-#{plat.get_os_name}-#{plat.get_os_version}.noarch.rpm" 7 | packages = %w(autoconf automake createrepo rsync gcc make rpmdevtools rpm-libs yum-utils rpm-sign) 8 | plat.provision_with "yum install --assumeyes #{packages.join(' ')}" 9 | plat.install_build_dependencies_with "yum install --assumeyes" 10 | plat.vmpooler_template "redhat-7-x86_64" 11 | end 12 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/el-8-aarch64.rb: -------------------------------------------------------------------------------- 1 | platform "el-8-aarch64" do |plat| 2 | plat.servicedir "/usr/lib/systemd/system" 3 | plat.defaultdir "/etc/sysconfig" 4 | plat.servicetype "systemd" 5 | 6 | packages = %w(autoconf automake createrepo gcc gcc-c++ rsync cmake make rpm-libs rpm-build libarchive) 7 | plat.provision_with "dnf install -y --allowerasing #{packages.join(' ')}" 8 | plat.install_build_dependencies_with "dnf install -y --allowerasing " 9 | plat.vmpooler_template "redhat-8-arm64" 10 | end 11 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/el-8-ppc64le.rb: -------------------------------------------------------------------------------- 1 | platform 'el-8-ppc64le' do |plat| 2 | plat.servicedir '/usr/lib/systemd/system' 3 | plat.defaultdir '/etc/sysconfig' 4 | plat.servicetype 'systemd' 5 | 6 | # Workaround for an issue with RedHat subscription metadata, see ITSYS-2543 7 | plat.provision_with('subscription-manager repos --disable rhel-8-for-ppc64le-baseos-rpms && subscription-manager repos --enable rhel-8-for-ppc64le-baseos-rpms') 8 | 9 | packages = %w( 10 | autoconf 11 | automake 12 | cmake 13 | gcc-c++ 14 | java-1.8.0-openjdk-devel 15 | libarchive 16 | libselinux-devel 17 | make 18 | patch 19 | perl-Getopt-Long 20 | readline-devel 21 | swig 22 | systemtap-sdt-devel 23 | zlib-devel 24 | ) 25 | 26 | plat.provision_with("dnf install -y --allowerasing #{packages.join(' ')}") 27 | plat.install_build_dependencies_with 'dnf install -y --allowerasing' 28 | plat.vmpooler_template 'redhat-8-power8' 29 | end 30 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/el-8-x86_64.rb: -------------------------------------------------------------------------------- 1 | platform "el-8-x86_64" do |plat| 2 | plat.servicedir "/usr/lib/systemd/system" 3 | plat.defaultdir "/etc/sysconfig" 4 | plat.servicetype "systemd" 5 | 6 | packages = %w(gcc gcc-c++ autoconf automake createrepo rsync cmake make rpm-libs rpm-build rpm-sign libtool libarchive) 7 | plat.provision_with "dnf install -y --allowerasing #{packages.join(' ')}" 8 | plat.install_build_dependencies_with "dnf install -y --allowerasing " 9 | plat.vmpooler_template "redhat-8-x86_64" 10 | end 11 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/el-9-aarch64.rb: -------------------------------------------------------------------------------- 1 | platform "el-9-aarch64" do |plat| 2 | plat.servicedir "/usr/lib/systemd/system" 3 | plat.defaultdir "/etc/sysconfig" 4 | plat.servicetype "systemd" 5 | 6 | packages = %w(autoconf automake createrepo gcc gcc-c++ rsync cmake make rpm-libs rpm-build libarchive) 7 | plat.provision_with "dnf install -y --allowerasing #{packages.join(' ')}" 8 | plat.install_build_dependencies_with "dnf install -y --allowerasing " 9 | plat.vmpooler_template "redhat-9-arm64" 10 | end 11 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/el-9-ppc64le.rb: -------------------------------------------------------------------------------- 1 | platform 'el-9-ppc64le' do |plat| 2 | plat.servicedir '/usr/lib/systemd/system' 3 | plat.defaultdir '/etc/sysconfig' 4 | plat.servicetype 'systemd' 5 | 6 | # Workaround for an issue with RedHat subscription metadata, see ITSYS-2543 7 | plat.provision_with('subscription-manager repos --disable rhel-9-for-ppc64le-baseos-rpms && subscription-manager repos --enable rhel-9-for-ppc64le-baseos-rpms --enable codeready-builder-for-rhel-9-ppc64le-rpms') 8 | 9 | packages = %w( 10 | autoconf 11 | automake 12 | cmake 13 | gcc-c++ 14 | java-1.8.0-openjdk-devel 15 | libarchive 16 | libselinux-devel 17 | make 18 | patch 19 | perl-Getopt-Long 20 | readline-devel 21 | swig 22 | systemtap-sdt-devel 23 | zlib-devel 24 | ) 25 | 26 | plat.provision_with("dnf install -y --allowerasing #{packages.join(' ')}") 27 | plat.install_build_dependencies_with 'dnf install -y --allowerasing' 28 | plat.vmpooler_template 'redhat-9-power9' 29 | end 30 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/el-9-x86_64.rb: -------------------------------------------------------------------------------- 1 | platform "el-9-x86_64" do |plat| 2 | plat.servicedir "/usr/lib/systemd/system" 3 | plat.defaultdir "/etc/sysconfig" 4 | plat.servicetype "systemd" 5 | 6 | packages = %w(gcc gcc-c++ autoconf automake createrepo rsync cmake make rpm-libs rpm-build rpm-sign libtool libarchive) 7 | plat.provision_with "dnf install -y --allowerasing #{packages.join(' ')}" 8 | plat.install_build_dependencies_with "dnf install -y --allowerasing " 9 | plat.vmpooler_template "redhat-9-x86_64" 10 | end 11 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/fedora-36-x86_64.rb: -------------------------------------------------------------------------------- 1 | platform 'fedora-36-x86_64' do |plat| 2 | plat.servicedir '/usr/lib/systemd/system' 3 | plat.defaultdir '/etc/sysconfig' 4 | plat.servicetype 'systemd' 5 | plat.dist 'fc36' 6 | 7 | packages = %w[ 8 | autoconf automake bzip2-devel gcc gcc-c++ libselinux-devel 9 | libsepol libsepol-devel make cmake pkgconfig readline-devel 10 | rpmdevtools rsync swig zlib-devel systemtap-sdt-devel 11 | perl-lib perl-FindBin 12 | ] 13 | plat.provision_with("/usr/bin/dnf install -y --best --allowerasing #{packages.join(' ')}") 14 | 15 | plat.install_build_dependencies_with '/usr/bin/dnf install -y --best --allowerasing' 16 | plat.vmpooler_template 'fedora-36-x86_64' 17 | end 18 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/fedora-38-x86_64.rb: -------------------------------------------------------------------------------- 1 | platform 'fedora-38-x86_64' do |plat| 2 | plat.servicedir '/usr/lib/systemd/system' 3 | plat.defaultdir '/etc/sysconfig' 4 | plat.servicetype 'systemd' 5 | plat.dist 'fc38' 6 | 7 | packages = %w[ 8 | autoconf automake bzip2-devel gcc gcc-c++ libselinux-devel 9 | libsepol libsepol-devel make cmake pkgconfig readline-devel 10 | rpmdevtools rsync swig zlib-devel systemtap-sdt-devel 11 | perl-lib perl-FindBin 12 | ] 13 | plat.provision_with("/usr/bin/dnf install -y --best --allowerasing #{packages.join(' ')}") 14 | 15 | plat.install_build_dependencies_with '/usr/bin/dnf install -y --best --allowerasing' 16 | plat.vmpooler_template 'fedora-38-x86_64' 17 | end 18 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/fedora-40-x86_64.rb: -------------------------------------------------------------------------------- 1 | platform 'fedora-40-x86_64' do |plat| 2 | plat.servicedir '/usr/lib/systemd/system' 3 | plat.defaultdir '/etc/sysconfig' 4 | plat.servicetype 'systemd' 5 | plat.dist 'fc40' 6 | 7 | packages = %w[ 8 | autoconf automake bzip2-devel gcc gcc-c++ libselinux-devel 9 | libsepol libsepol-devel make cmake pkgconfig readline-devel 10 | rpmdevtools rsync swig zlib-devel systemtap-sdt-devel 11 | perl-lib perl-FindBin 12 | ] 13 | plat.provision_with("/usr/bin/dnf install -y --best --allowerasing #{packages.join(' ')}") 14 | 15 | plat.install_build_dependencies_with '/usr/bin/dnf install -y --best --allowerasing' 16 | plat.vmpooler_template 'fedora-40-x86_64' 17 | end 18 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/osx-11-arm64.rb: -------------------------------------------------------------------------------- 1 | platform "osx-11-arm64" do |plat| 2 | plat.servicetype "launchd" 3 | plat.servicedir "/Library/LaunchDaemons" 4 | plat.codename "bigsur" 5 | 6 | plat.provision_with "export HOMEBREW_NO_EMOJI=true" 7 | plat.provision_with "export HOMEBREW_VERBOSE=true" 8 | plat.provision_with "export HOMEBREW_NO_ANALYTICS=1" 9 | 10 | plat.provision_with "sudo dscl . -create /Users/test" 11 | plat.provision_with "sudo dscl . -create /Users/test UserShell /bin/bash" 12 | plat.provision_with "sudo dscl . -create /Users/test UniqueID 1001" 13 | plat.provision_with "sudo dscl . -create /Users/test PrimaryGroupID 1000" 14 | plat.provision_with "sudo dscl . -create /Users/test NFSHomeDirectory /Users/test" 15 | plat.provision_with "sudo dscl . -passwd /Users/test password" 16 | plat.provision_with "sudo dscl . -merge /Groups/admin GroupMembership test" 17 | plat.provision_with "echo 'test ALL=(ALL:ALL) NOPASSWD: ALL' > /etc/sudoers.d/username" 18 | plat.provision_with "mkdir -p /etc/homebrew" 19 | plat.provision_with "cd /etc/homebrew" 20 | plat.provision_with "createhomedir -c -u test" 21 | plat.provision_with %(su test -c 'echo | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"') 22 | plat.vmpooler_template "macos-112-x86_64" 23 | plat.cross_compiled true 24 | end 25 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/osx-11-x86_64.rb: -------------------------------------------------------------------------------- 1 | platform "osx-11-x86_64" do |plat| 2 | plat.servicetype "launchd" 3 | plat.servicedir "/Library/LaunchDaemons" 4 | plat.codename "bigsur" 5 | 6 | plat.provision_with "export HOMEBREW_NO_EMOJI=true" 7 | plat.provision_with "export HOMEBREW_VERBOSE=true" 8 | plat.provision_with "export HOMEBREW_NO_ANALYTICS=1" 9 | 10 | plat.provision_with "sudo dscl . -create /Users/test" 11 | plat.provision_with "sudo dscl . -create /Users/test UserShell /bin/bash" 12 | plat.provision_with "sudo dscl . -create /Users/test UniqueID 1001" 13 | plat.provision_with "sudo dscl . -create /Users/test PrimaryGroupID 1000" 14 | plat.provision_with "sudo dscl . -create /Users/test NFSHomeDirectory /Users/test" 15 | plat.provision_with "sudo dscl . -passwd /Users/test password" 16 | plat.provision_with "sudo dscl . -merge /Groups/admin GroupMembership test" 17 | plat.provision_with "echo 'test ALL=(ALL:ALL) NOPASSWD: ALL' > /etc/sudoers.d/username" 18 | plat.provision_with "mkdir -p /etc/homebrew" 19 | plat.provision_with "cd /etc/homebrew" 20 | plat.provision_with "createhomedir -c -u test" 21 | plat.provision_with %Q(su test -c 'echo | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"') 22 | plat.vmpooler_template "macos-112-x86_64" 23 | end 24 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/osx-12-arm64.rb: -------------------------------------------------------------------------------- 1 | platform 'osx-12-arm64' do |plat| 2 | plat.servicetype 'launchd' 3 | plat.servicedir '/Library/LaunchDaemons' 4 | plat.codename 'monterey' 5 | 6 | plat.provision_with 'export HOMEBREW_NO_EMOJI=true' 7 | plat.provision_with 'export HOMEBREW_VERBOSE=true' 8 | plat.provision_with "export HOMEBREW_NO_ANALYTICS=1" 9 | 10 | plat.provision_with 'sudo dscl . -create /Users/test' 11 | plat.provision_with 'sudo dscl . -create /Users/test UserShell /bin/bash' 12 | plat.provision_with 'sudo dscl . -create /Users/test UniqueID 1001' 13 | plat.provision_with 'sudo dscl . -create /Users/test PrimaryGroupID 1000' 14 | plat.provision_with 'sudo dscl . -create /Users/test NFSHomeDirectory /Users/test' 15 | plat.provision_with 'sudo dscl . -passwd /Users/test password' 16 | plat.provision_with 'sudo dscl . -merge /Groups/admin GroupMembership test' 17 | plat.provision_with 'echo "test ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/username' 18 | plat.provision_with 'mkdir -p /etc/homebrew' 19 | plat.provision_with 'cd /etc/homebrew' 20 | plat.provision_with 'createhomedir -c -u test' 21 | plat.provision_with 'su test -c \'echo | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"\'' 22 | plat.vmpooler_template 'macos-12-x86_64' 23 | plat.cross_compiled true 24 | end 25 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/osx-12-x86_64.rb: -------------------------------------------------------------------------------- 1 | platform "osx-12-x86_64" do |plat| 2 | plat.servicetype "launchd" 3 | plat.servicedir "/Library/LaunchDaemons" 4 | plat.codename "monterey" 5 | 6 | plat.provision_with "export HOMEBREW_NO_EMOJI=true" 7 | plat.provision_with "export HOMEBREW_VERBOSE=true" 8 | plat.provision_with "export HOMEBREW_NO_ANALYTICS=1" 9 | 10 | plat.provision_with "sudo dscl . -create /Users/test" 11 | plat.provision_with "sudo dscl . -create /Users/test UserShell /bin/bash" 12 | plat.provision_with "sudo dscl . -create /Users/test UniqueID 1001" 13 | plat.provision_with "sudo dscl . -create /Users/test PrimaryGroupID 1000" 14 | plat.provision_with "sudo dscl . -create /Users/test NFSHomeDirectory /Users/test" 15 | plat.provision_with "sudo dscl . -passwd /Users/test password" 16 | plat.provision_with "sudo dscl . -merge /Groups/admin GroupMembership test" 17 | plat.provision_with "echo 'test ALL=(ALL:ALL) NOPASSWD: ALL' > /etc/sudoers.d/username" 18 | plat.provision_with "mkdir -p /etc/homebrew" 19 | plat.provision_with "cd /etc/homebrew" 20 | plat.provision_with "createhomedir -c -u test" 21 | plat.provision_with %Q(su test -c 'echo | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"') 22 | plat.vmpooler_template "macos-12-x86_64" 23 | end 24 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/osx-13-arm64.rb: -------------------------------------------------------------------------------- 1 | platform 'osx-13-arm64' do |plat| 2 | plat.brew '/opt/homebrew/bin/brew' 3 | plat.servicetype 'launchd' 4 | plat.servicedir '/Library/LaunchDaemons' 5 | plat.codename 'ventura' 6 | 7 | plat.provision_with 'export HOMEBREW_NO_EMOJI=true' 8 | plat.provision_with 'export HOMEBREW_VERBOSE=true' 9 | plat.provision_with "export HOMEBREW_NO_ANALYTICS=1" 10 | 11 | plat.provision_with 'sudo dscl . -create /Users/test' 12 | plat.provision_with 'sudo dscl . -create /Users/test UserShell /bin/bash' 13 | plat.provision_with 'sudo dscl . -create /Users/test UniqueID 1001' 14 | plat.provision_with 'sudo dscl . -create /Users/test PrimaryGroupID 1000' 15 | plat.provision_with 'sudo dscl . -create /Users/test NFSHomeDirectory /Users/test' 16 | plat.provision_with 'sudo dscl . -passwd /Users/test password' 17 | plat.provision_with 'sudo dscl . -merge /Groups/admin GroupMembership test' 18 | plat.provision_with 'echo "test ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/username' 19 | plat.provision_with 'mkdir -p /etc/homebrew' 20 | plat.provision_with 'cd /etc/homebrew' 21 | plat.provision_with 'createhomedir -c -u test' 22 | plat.provision_with 'su test -c \'echo | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"\'' 23 | plat.vmpooler_template 'macos-13-arm64' 24 | end 25 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/osx-13-x86_64.rb: -------------------------------------------------------------------------------- 1 | platform "osx-13-x86_64" do |plat| 2 | plat.servicetype "launchd" 3 | plat.servicedir "/Library/LaunchDaemons" 4 | plat.codename "ventura" 5 | 6 | plat.provision_with "export HOMEBREW_NO_EMOJI=true" 7 | plat.provision_with "export HOMEBREW_VERBOSE=true" 8 | plat.provision_with "export HOMEBREW_NO_ANALYTICS=1" 9 | 10 | plat.provision_with "sudo dscl . -create /Users/test" 11 | plat.provision_with "sudo dscl . -create /Users/test UserShell /bin/bash" 12 | plat.provision_with "sudo dscl . -create /Users/test UniqueID 1001" 13 | plat.provision_with "sudo dscl . -create /Users/test PrimaryGroupID 1000" 14 | plat.provision_with "sudo dscl . -create /Users/test NFSHomeDirectory /Users/test" 15 | plat.provision_with "sudo dscl . -passwd /Users/test password" 16 | plat.provision_with "sudo dscl . -merge /Groups/admin GroupMembership test" 17 | plat.provision_with "echo 'test ALL=(ALL:ALL) NOPASSWD: ALL' > /etc/sudoers.d/username" 18 | plat.provision_with "mkdir -p /etc/homebrew" 19 | plat.provision_with "cd /etc/homebrew" 20 | plat.provision_with "createhomedir -c -u test" 21 | plat.provision_with %Q(su test -c 'echo | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"') 22 | plat.vmpooler_template "macos-13-x86_64" 23 | end 24 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/osx-14-arm64.rb: -------------------------------------------------------------------------------- 1 | platform 'osx-14-arm64' do |plat| 2 | plat.brew '/opt/homebrew/bin/brew' 3 | plat.servicetype 'launchd' 4 | plat.servicedir '/Library/LaunchDaemons' 5 | plat.codename 'sonoma' 6 | 7 | plat.provision_with 'export HOMEBREW_NO_EMOJI=true' 8 | plat.provision_with 'export HOMEBREW_VERBOSE=true' 9 | plat.provision_with "export HOMEBREW_NO_ANALYTICS=1" 10 | 11 | plat.provision_with 'sudo dscl . -create /Users/test' 12 | plat.provision_with 'sudo dscl . -create /Users/test UserShell /bin/bash' 13 | plat.provision_with 'sudo dscl . -create /Users/test UniqueID 1001' 14 | plat.provision_with 'sudo dscl . -create /Users/test PrimaryGroupID 1000' 15 | plat.provision_with 'sudo dscl . -create /Users/test NFSHomeDirectory /Users/test' 16 | plat.provision_with 'sudo dscl . -passwd /Users/test password' 17 | plat.provision_with 'sudo dscl . -merge /Groups/admin GroupMembership test' 18 | plat.provision_with 'echo "test ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/username' 19 | plat.provision_with 'mkdir -p /etc/homebrew' 20 | plat.provision_with 'cd /etc/homebrew' 21 | plat.provision_with 'createhomedir -c -u test' 22 | plat.provision_with 'su test -c \'echo | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"\'' 23 | plat.vmpooler_template 'macos-14-arm64' 24 | end 25 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/osx-14-x86_64.rb: -------------------------------------------------------------------------------- 1 | platform "osx-14-x86_64" do |plat| 2 | plat.servicetype "launchd" 3 | plat.servicedir "/Library/LaunchDaemons" 4 | plat.codename "sonoma" 5 | 6 | plat.provision_with "export HOMEBREW_NO_EMOJI=true" 7 | plat.provision_with "export HOMEBREW_VERBOSE=true" 8 | plat.provision_with "export HOMEBREW_NO_ANALYTICS=1" 9 | 10 | plat.provision_with "sudo dscl . -create /Users/test" 11 | plat.provision_with "sudo dscl . -create /Users/test UserShell /bin/bash" 12 | plat.provision_with "sudo dscl . -create /Users/test UniqueID 1001" 13 | plat.provision_with "sudo dscl . -create /Users/test PrimaryGroupID 1000" 14 | plat.provision_with "sudo dscl . -create /Users/test NFSHomeDirectory /Users/test" 15 | plat.provision_with "sudo dscl . -passwd /Users/test password" 16 | plat.provision_with "sudo dscl . -merge /Groups/admin GroupMembership test" 17 | plat.provision_with "echo 'test ALL=(ALL:ALL) NOPASSWD: ALL' > /etc/sudoers.d/username" 18 | plat.provision_with "mkdir -p /etc/homebrew" 19 | plat.provision_with "cd /etc/homebrew" 20 | plat.provision_with "createhomedir -c -u test" 21 | plat.provision_with %Q(su test -c 'echo | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"') 22 | plat.vmpooler_template "macos-14-x86_64" 23 | end 24 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/redhatfips-7-x86_64.rb: -------------------------------------------------------------------------------- 1 | platform "redhatfips-7-x86_64" do |plat| 2 | plat.servicedir "/usr/lib/systemd/system" 3 | plat.defaultdir "/etc/sysconfig" 4 | plat.servicetype "systemd" 5 | 6 | plat.add_build_repository "http://pl-build-tools.delivery.puppetlabs.net/yum/pl-build-tools-release-el-7.noarch.rpm" 7 | packages = %w( 8 | autoconf 9 | automake 10 | createrepo 11 | gcc 12 | java-1.8.0-openjdk-devel 13 | libsepol 14 | libsepol-devel 15 | libselinux-devel 16 | make 17 | openssl-devel 18 | pkgconfig 19 | readline-devel 20 | rpmdevtools 21 | rpm-build 22 | rpm-libs 23 | rpm-sign 24 | rsync 25 | swig 26 | yum-utils 27 | zlib-devel 28 | ) 29 | plat.provision_with "yum install --assumeyes #{packages.join(' ')}" 30 | plat.install_build_dependencies_with "yum install --assumeyes" 31 | plat.vmpooler_template "redhat-fips-7-x86_64" 32 | end 33 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/redhatfips-8-x86_64.rb: -------------------------------------------------------------------------------- 1 | platform "redhatfips-8-x86_64" do |plat| 2 | plat.servicedir "/usr/lib/systemd/system" 3 | plat.defaultdir "/etc/sysconfig" 4 | plat.servicetype "systemd" 5 | 6 | packages = %w( 7 | autoconf 8 | automake 9 | cmake 10 | gcc-c++ 11 | java-1.8.0-openjdk-devel 12 | libarchive 13 | libsepol-devel 14 | libselinux-devel 15 | openssl-devel 16 | pkgconfig 17 | readline-devel 18 | rpmdevtools 19 | rpm-build 20 | rsync 21 | swig 22 | systemtap-sdt-devel 23 | yum-utils 24 | zlib-devel 25 | ) 26 | 27 | plat.provision_with "dnf install -y --allowerasing #{packages.join(' ')}" 28 | plat.install_build_dependencies_with "dnf install -y --allowerasing " 29 | plat.vmpooler_template "redhat-fips-8-x86_64" 30 | end 31 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/redhatfips-9-x86_64.rb: -------------------------------------------------------------------------------- 1 | platform "redhatfips-9-x86_64" do |plat| 2 | plat.servicedir "/usr/lib/systemd/system" 3 | plat.defaultdir "/etc/sysconfig" 4 | plat.servicetype "systemd" 5 | 6 | packages = %w( 7 | autoconf 8 | automake 9 | cmake 10 | gcc-c++ 11 | java-1.8.0-openjdk-devel 12 | libarchive 13 | libsepol-devel 14 | libselinux-devel 15 | openssl-devel 16 | pkgconfig 17 | readline-devel 18 | rpmdevtools 19 | rpm-build 20 | rsync 21 | swig 22 | systemtap-sdt-devel 23 | yum-utils 24 | zlib-devel 25 | ) 26 | 27 | plat.provision_with "dnf install -y --allowerasing #{packages.join(' ')}" 28 | plat.install_build_dependencies_with "dnf install -y --allowerasing " 29 | plat.vmpooler_template "redhat-fips-9-x86_64" 30 | end 31 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/sles-12-x86_64.rb: -------------------------------------------------------------------------------- 1 | platform "sles-12-x86_64" do |plat| 2 | plat.servicedir "/usr/lib/systemd/system" 3 | plat.defaultdir "/etc/sysconfig" 4 | plat.servicetype "systemd" 5 | 6 | plat.add_build_repository "http://pl-build-tools.delivery.puppetlabs.net/yum/pl-build-tools-release-#{plat.get_os_name}-#{plat.get_os_version}.noarch.rpm" 7 | packages = %w(aaa_base autoconf automake rsync gcc make rpm-build) 8 | plat.provision_with "zypper -n --no-gpg-checks install -y #{packages.join(' ')}" 9 | plat.install_build_dependencies_with "zypper -n --no-gpg-checks install -y" 10 | plat.vmpooler_template "sles-12-x86_64" 11 | end 12 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/sles-15-x86_64.rb: -------------------------------------------------------------------------------- 1 | platform "sles-15-x86_64" do |plat| 2 | plat.servicedir "/usr/lib/systemd/system" 3 | plat.defaultdir "/etc/sysconfig" 4 | plat.servicetype "systemd" 5 | 6 | packages = %w(aaa_base autoconf automake rsync gcc gcc-c++ make rpm-build gettext-tools cmake) 7 | plat.provision_with "zypper -n --no-gpg-checks install -y #{packages.join(' ')}" 8 | plat.install_build_dependencies_with "zypper -n --no-gpg-checks install -y" 9 | plat.vmpooler_template "sles-15-x86_64" 10 | end 11 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/solaris-11-i386.rb: -------------------------------------------------------------------------------- 1 | platform "solaris-11-i386" do |plat| 2 | plat.servicedir "/lib/svc/manifest" 3 | plat.defaultdir "/lib/svc/method" 4 | plat.servicetype "smf" 5 | 6 | plat.vmpooler_template "solaris-11-x86_64" 7 | plat.add_build_repository "http://solaris-11-reposync.delivery.puppetlabs.net:81", "puppetlabs.com" 8 | plat.install_build_dependencies_with "pkg install ", " || [[ $? -eq 4 ]]" 9 | end 10 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/solaris-11-sparc.rb: -------------------------------------------------------------------------------- 1 | platform "solaris-11-sparc" do |plat| 2 | plat.servicedir "/lib/svc/manifest" 3 | plat.defaultdir "/lib/svc/method" 4 | plat.servicetype "smf" 5 | 6 | plat.cross_compiled true 7 | plat.vmpooler_template "solaris-11-x86_64" 8 | plat.add_build_repository "http://solaris-11-reposync.delivery.puppetlabs.net:81", "puppetlabs.com" 9 | plat.install_build_dependencies_with "pkg install ", " || [[ $? -eq 4 ]]" 10 | end 11 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/ubuntu-18.04-aarch64.rb: -------------------------------------------------------------------------------- 1 | platform "ubuntu-18.04-aarch64" do |plat| 2 | plat.servicedir "/lib/systemd/system" 3 | plat.defaultdir "/etc/default" 4 | plat.servicetype "systemd" 5 | plat.codename "bionic" 6 | 7 | packages = %w( 8 | autoconf 9 | build-essential 10 | cmake 11 | debhelper 12 | devscripts 13 | fakeroot 14 | libbz2-dev 15 | libreadline-dev 16 | libselinux1-dev 17 | openjdk-8-jre-headless 18 | pkg-config 19 | quilt 20 | rsync 21 | swig 22 | systemtap-sdt-dev 23 | zlib1g-dev 24 | ) 25 | plat.provision_with "export DEBIAN_FRONTEND=noninteractive; apt-get update -qq; apt-get install -qy --no-install-recommends #{packages.join(' ')}" 26 | plat.install_build_dependencies_with "DEBIAN_FRONTEND=noninteractive; apt-get install -qy --no-install-recommends " 27 | plat.vmpooler_template "ubuntu-1804-arm64" 28 | end 29 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/ubuntu-18.04-amd64.rb: -------------------------------------------------------------------------------- 1 | platform "ubuntu-18.04-amd64" do |plat| 2 | plat.servicedir "/lib/systemd/system" 3 | plat.defaultdir "/etc/default" 4 | plat.servicetype "systemd" 5 | plat.codename "bionic" 6 | 7 | plat.add_build_repository "http://pl-build-tools.delivery.puppetlabs.net/debian/pl-build-tools-release-#{plat.get_codename}.deb" 8 | packages = %w(build-essential devscripts make quilt pkg-config debhelper rsync fakeroot) 9 | plat.provision_with "export DEBIAN_FRONTEND=noninteractive; apt-get update -qq; apt-get install -qy --no-install-recommends #{packages.join(' ')}" 10 | plat.install_build_dependencies_with "export DEBIAN_FRONTEND=noninteractive; apt-get install -qy --no-install-recommends " 11 | plat.vmpooler_template "ubuntu-1804-x86_64" 12 | end 13 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/ubuntu-20.04-aarch64.rb: -------------------------------------------------------------------------------- 1 | platform "ubuntu-20.04-aarch64" do |plat| 2 | plat.servicedir "/lib/systemd/system" 3 | plat.defaultdir "/etc/default" 4 | plat.servicetype "systemd" 5 | plat.codename "focal" 6 | 7 | packages = %w(build-essential devscripts make quilt pkg-config debhelper rsync fakeroot cmake) 8 | plat.provision_with "export DEBIAN_FRONTEND=noninteractive; apt-get update -qq; apt-get install -qy --no-install-recommends #{packages.join(' ')}" 9 | plat.install_build_dependencies_with "DEBIAN_FRONTEND=noninteractive; apt-get install -qy --no-install-recommends " 10 | plat.vmpooler_template "ubuntu-2004-arm64" 11 | end 12 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/ubuntu-20.04-amd64.rb: -------------------------------------------------------------------------------- 1 | platform "ubuntu-20.04-amd64" do |plat| 2 | plat.servicedir "/lib/systemd/system" 3 | plat.defaultdir "/etc/default" 4 | plat.servicetype "systemd" 5 | plat.codename "focal" 6 | 7 | # Temporary fix to add focal-updates.list repo file because it is missing from the vmpooler image 8 | plat.provision_with "echo 'deb https://artifactory.delivery.puppetlabs.net/artifactory/ubuntu__remote focal-updates main restricted universe multiverse' > /etc/apt/sources.list.d/focal-updates.list; 9 | echo 'deb-src https://artifactory.delivery.puppetlabs.net/artifactory/ubuntu__remote focal-updates main restricted universe multiverse' >> /etc/apt/sources.list.d/focal-updates.list" 10 | 11 | packages = %w(build-essential devscripts make quilt pkg-config debhelper rsync fakeroot cmake) 12 | 13 | plat.provision_with "export DEBIAN_FRONTEND=noninteractive; apt-get update -qq; apt-get install -qy --no-install-recommends #{packages.join(' ')}" 14 | plat.provision_with "curl https://apt.puppet.com/DEB-GPG-KEY-puppet-20250406 | apt-key add -" 15 | plat.install_build_dependencies_with "DEBIAN_FRONTEND=noninteractive; apt-get install -qy --no-install-recommends " 16 | plat.vmpooler_template "ubuntu-2004-x86_64" 17 | end 18 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/ubuntu-22.04-aarch64.rb: -------------------------------------------------------------------------------- 1 | platform "ubuntu-22.04-aarch64" do |plat| 2 | plat.servicedir "/lib/systemd/system" 3 | plat.defaultdir "/etc/default" 4 | plat.servicetype "systemd" 5 | plat.codename "jammy" 6 | 7 | packages = %w(build-essential devscripts make quilt pkg-config debhelper rsync fakeroot cmake) 8 | plat.provision_with "export DEBIAN_FRONTEND=noninteractive; apt-get update -qq; apt-get install -qy --no-install-recommends #{packages.join(' ')}" 9 | plat.install_build_dependencies_with "DEBIAN_FRONTEND=noninteractive; apt-get install -qy --no-install-recommends " 10 | plat.vmpooler_template "ubuntu-2204-arm64" 11 | end 12 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/ubuntu-22.04-amd64.rb: -------------------------------------------------------------------------------- 1 | platform "ubuntu-22.04-amd64" do |plat| 2 | plat.servicedir "/lib/systemd/system" 3 | plat.defaultdir "/etc/default" 4 | plat.servicetype "systemd" 5 | plat.codename "jammy" 6 | 7 | packages = %w(build-essential devscripts make quilt pkg-config debhelper rsync fakeroot cmake) 8 | plat.provision_with "export DEBIAN_FRONTEND=noninteractive; apt-get update -qq; apt-get install -qy --no-install-recommends #{packages.join(' ')}" 9 | plat.provision_with "curl https://apt.puppet.com/DEB-GPG-KEY-puppet-20250406 | apt-key add -" 10 | plat.install_build_dependencies_with "DEBIAN_FRONTEND=noninteractive; apt-get install -qy --no-install-recommends " 11 | plat.vmpooler_template "ubuntu-2204-x86_64" 12 | end 13 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/ubuntu-24.04-aarch64.rb: -------------------------------------------------------------------------------- 1 | platform "ubuntu-24.04-aarch64" do |plat| 2 | plat.servicedir "/lib/systemd/system" 3 | plat.defaultdir "/etc/default" 4 | plat.servicetype "systemd" 5 | plat.codename "noble" 6 | 7 | packages = %w(build-essential devscripts make quilt pkg-config debhelper rsync fakeroot cmake) 8 | plat.provision_with "export DEBIAN_FRONTEND=noninteractive; apt-get update -qq; apt-get install -qy --no-install-recommends #{packages.join(' ')}" 9 | plat.install_build_dependencies_with "DEBIAN_FRONTEND=noninteractive; apt-get install -qy --no-install-recommends " 10 | plat.vmpooler_template "ubuntu-2404-arm64" 11 | end 12 | -------------------------------------------------------------------------------- /lib/vanagon/platform/defaults/ubuntu-24.04-amd64.rb: -------------------------------------------------------------------------------- 1 | platform "ubuntu-24.04-amd64" do |plat| 2 | plat.servicedir "/lib/systemd/system" 3 | plat.defaultdir "/etc/default" 4 | plat.servicetype "systemd" 5 | plat.codename "noble" 6 | 7 | packages = %w(build-essential devscripts make quilt pkg-config debhelper rsync fakeroot cmake curl) 8 | plat.provision_with "export DEBIAN_FRONTEND=noninteractive; apt-get update -qq; apt-get install -qy --no-install-recommends #{packages.join(' ')}" 9 | plat.provision_with "curl https://apt.puppet.com/DEB-GPG-KEY-puppet-20250406 | apt-key add -" 10 | plat.install_build_dependencies_with "DEBIAN_FRONTEND=noninteractive; apt-get install -qy --no-install-recommends " 11 | plat.vmpooler_template "ubuntu-2404-x86_64" 12 | end 13 | -------------------------------------------------------------------------------- /lib/vanagon/platform/rpm/aix.rb: -------------------------------------------------------------------------------- 1 | class Vanagon 2 | class Platform 3 | class RPM 4 | # AIX is special. This subclassing gives us the chance to define some sane 5 | # defaults for aix without cluttering the main rpm class in if statements. 6 | class AIX < Vanagon::Platform::RPM 7 | def rpm_defines 8 | %(--define '_topdir $(tempdir)/rpmbuild' ) 9 | end 10 | 11 | # Constructor. Sets up some defaults for the aix platform and calls the parent constructor 12 | # 13 | # @param name [String] name of the platform 14 | # @return [Vanagon::Platform::RPM::AIX] the rpm derived platform with the given name 15 | def initialize(name) 16 | @name = name 17 | @make = "/usr/bin/gmake" 18 | @tar = "/opt/freeware/bin/tar" 19 | @patch = "/opt/freeware/bin/patch" 20 | @sed = "/opt/freeware/bin/sed" 21 | @shasum = "/opt/freeware/bin/sha1sum" 22 | @num_cores = "lsdev -Cc processor |wc -l" 23 | @install = "/opt/freeware/bin/install" 24 | @rpmbuild = "/usr/bin/rpm" 25 | super(name) 26 | end 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/vanagon/platform/rpm/eos.rb: -------------------------------------------------------------------------------- 1 | class Vanagon 2 | class Platform 3 | class RPM 4 | class EOS < Vanagon::Platform::RPM 5 | # The specific bits used to generate an EOS package for a given project 6 | # 7 | # @param project [Vanagon::Project] project to build an EOS package of 8 | # @return [Array] list of commands required to build the EOS package 9 | # for the given project from an rpm or a swix 10 | def generate_package(project) 11 | # If nothing is passed in as platform type, default to building a swix package 12 | if project.platform.package_type.nil? || project.platform.package_type.empty? 13 | return generate_swix_package(project) 14 | else 15 | case project.platform.package_type 16 | when "rpm" 17 | return super(project) 18 | when "swix" 19 | return generate_swix_package(project) 20 | else 21 | fail "I don't know how to build package type '#{project.platform.package_type}' for EOS. Teach me?" 22 | end 23 | end 24 | end 25 | 26 | # Method to derive the package name for the project 27 | # 28 | # @param project [Vanagon::Project] project to name 29 | # @return [String] name of the EOS package for this project 30 | def package_name(project) 31 | # If nothing is passed in as platform type, default to building a swix package 32 | if project.platform.package_type.nil? || project.platform.package_type.empty? 33 | return swix_package_name(project) 34 | else 35 | case project.platform.package_type 36 | when "rpm" 37 | return super(project) 38 | when "swix" 39 | return swix_package_name(project) 40 | else 41 | fail "I don't know how to name package type '#{project.platform.package_type}' for EOS. Teach me?" 42 | end 43 | end 44 | end 45 | 46 | # The specific bits used to generate an SWIX package for a given project 47 | # 48 | # @param project [Vanagon::Project] project to build a SWIX package of 49 | # @return [Array] list of commands required to build the SWIX package 50 | # for the given project from an rpm 51 | def generate_swix_package(project) 52 | target_dir = project.repo ? output_dir(project.repo) : output_dir 53 | commands = ["bash -c 'mkdir -p $(tempdir)/rpmbuild/{SOURCES,SPECS,BUILD,RPMS,SRPMS}'", 54 | "cp #{project.name}-#{project.version}.tar.gz $(tempdir)/rpmbuild/SOURCES", 55 | "cp file-list-for-rpm $(tempdir)/rpmbuild/SOURCES", 56 | "cp #{project.name}.spec $(tempdir)/rpmbuild/SPECS", 57 | "PATH=/opt/freeware/bin:$$PATH #{@rpmbuild} -bb --target #{@architecture} #{rpm_defines} $(tempdir)/rpmbuild/SPECS/#{project.name}.spec", 58 | "mkdir -p output/#{target_dir}", 59 | "cp $(tempdir)/rpmbuild/*RPMS/**/*.rpm ./output/#{target_dir}"] 60 | 61 | 62 | pkgname_swix = swix_package_name(project) 63 | pkgname_rpm = pkgname_swix.sub(/swix$/, 'rpm') 64 | commands += ["echo 'format: 1' > ./output/#{target_dir}/manifest.txt", 65 | "echo \"primaryRpm: #{pkgname_rpm}\" >> ./output/#{target_dir}/manifest.txt", 66 | "echo #{pkgname_rpm}-sha1: `sha1sum ./output/#{target_dir}/#{pkgname_rpm}`", 67 | "cd ./output/#{target_dir}/ && zip #{pkgname_swix} manifest.txt #{pkgname_rpm}", 68 | "rm ./output/#{target_dir}/manifest.txt ./output/#{target_dir}/#{pkgname_rpm}"] 69 | 70 | commands 71 | end 72 | 73 | # Method to derive the package name for the project 74 | # 75 | # @param project [Vanagon::Project] project to name 76 | # @return [String] name of the SWIX package for this project 77 | def swix_package_name(project) 78 | "#{project.name}-#{project.version}-#{project.release}.#{os_name}#{os_version}.#{project.noarch ? 'noarch' : @architecture}.swix" 79 | end 80 | end 81 | end 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /lib/vanagon/platform/rpm/sles.rb: -------------------------------------------------------------------------------- 1 | class Vanagon 2 | class Platform 3 | class RPM 4 | # SLES is special, mainly in the differences between yum and zypper, 5 | # so here we subclass SLES off of rpm. 6 | class SLES < Vanagon::Platform::RPM 7 | # Helper to setup a zypper repository on a target system 8 | # 9 | # @param definition [String] the repo setup URI or RPM file 10 | # @return [Array] A list of commands to add a zypper repo for the build system 11 | def add_repository(definition) 12 | definition = URI.parse(definition) 13 | if @os_version == '10' 14 | flag = 'sa' 15 | else 16 | flag = 'ar' 17 | end 18 | 19 | commands = [] 20 | 21 | if definition.scheme =~ /^(http|ftp)/ 22 | if File.extname(definition.path) == '.rpm' 23 | # repo definition is an rpm (like puppetlabs-release) 24 | commands << "curl --silent --show-error --fail -o local.rpm '#{definition}'; rpm -Uvh local.rpm; rm -f local.rpm" 25 | else 26 | commands << "yes | zypper -n --no-gpg-checks #{flag} -t YUM --repo '#{definition}'" 27 | end 28 | end 29 | 30 | commands 31 | end 32 | end 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /lib/vanagon/platform/rpm/wrl.rb: -------------------------------------------------------------------------------- 1 | class Vanagon 2 | class Platform 3 | class RPM 4 | # This platform definition was created to account for oddities with 5 | # the RPM available on WindRiver Linux based systems. WRL uses RPMv5 6 | # and some of the WRL-based OS platforms we support (e.g, HuaweiOS) 7 | # do not have package repo systems or support for installing remote 8 | # RPMs via urls 9 | class WRL < Vanagon::Platform::RPM 10 | # Some WRL RPM platforms (e.g, HuaweiOS) don't allow you to 11 | # install remote packages via url, so we'll do a dance to 12 | # download them via curl and then perform the installs locally. 13 | # This method generates a shell script to be executed on the 14 | # system to do this. 15 | # 16 | # @param build_dependencies [Array] list of all build dependencies to install 17 | # @return [String] a command to install all of the build dependencies 18 | def install_build_dependencies(build_dependencies) 19 | commands = [] 20 | unless build_dependencies.empty? 21 | commands << "tmpdir=$(#{mktemp})" 22 | commands << "cd ${tmpdir}" 23 | build_dependencies.each do |build_dependency| 24 | if build_dependency =~ /^http.*\.rpm$/ 25 | # We're downloading each package individually so 26 | # failures are easier to troubleshoot 27 | commands << %(curl --remote-name --location --fail --silent #{build_dependency} && echo "Successfully downloaded #{build_dependency}") 28 | end 29 | end 30 | # Install the downloaded packages 31 | commands << "rpm -Uvh --nodeps --replacepkgs ${tmpdir}/*.rpm" 32 | end 33 | 34 | commands.join(' && ') 35 | end 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/vanagon/utilities/extra_files_signer.rb: -------------------------------------------------------------------------------- 1 | class Vanagon 2 | module Utilities 3 | module ExtraFilesSigner 4 | class << self 5 | def commands(project, mktemp, source_dir) # rubocop:disable Metrics/AbcSize 6 | tempdir = nil 7 | commands = [] 8 | # Skip signing extra files if logging into the signing_host fails 9 | # This enables things like CI being able to sign the additional files, 10 | # but locally triggered builds by developers who don't have access to 11 | # the signing host just print a message and skip the signing. 12 | Vanagon::Utilities.retry_with_timeout(3, 5) do 13 | tempdir = Vanagon::Utilities::remote_ssh_command("#{project.signing_username}@#{project.signing_hostname}", "#{mktemp} 2>/dev/null", return_command_output: true) 14 | end 15 | 16 | remote_host = "#{project.signing_username}@#{project.signing_hostname}" 17 | remote_destination_directory = "#{remote_host}:#{tempdir}" 18 | remote_signing_script_path = File.join(tempdir, File.basename('sign_extra_file')) 19 | extra_flags = '' 20 | extra_flags = '--extended-attributes' if project.platform.is_macos? 21 | 22 | project.extra_files_to_sign.each do |file| 23 | remote_file_to_sign_path = File.join(tempdir, File.basename(file)) 24 | local_source_path = File.join('$(tempdir)', source_dir, file) 25 | remote_source_path = "#{remote_host}:#{remote_file_to_sign_path}" 26 | local_destination_path = local_source_path 27 | 28 | commands += [ 29 | "#{Vanagon::Utilities.ssh_command} #{remote_host} \"echo '#{project.signing_command} #{remote_file_to_sign_path}' > #{remote_signing_script_path}\"", 30 | "rsync -e '#{Vanagon::Utilities.ssh_command}' --verbose --recursive --hard-links --links --no-perms --no-owner --no-group #{extra_flags} #{local_source_path} #{remote_destination_directory}", 31 | "#{Vanagon::Utilities.ssh_command} #{remote_host} /bin/bash #{remote_signing_script_path}", 32 | "rsync -e '#{Vanagon::Utilities.ssh_command}' --verbose --recursive --hard-links --links --no-perms --no-owner --no-group #{extra_flags} #{remote_source_path} #{local_destination_path}" 33 | ] 34 | end 35 | 36 | commands 37 | rescue RuntimeError 38 | require 'vanagon/logger' 39 | VanagonLogger.error "Unable to connect to #{project.signing_username}@#{project.signing_hostname}, skipping signing extra files: #{project.extra_files_to_sign.join(',')}" 40 | raise if ENV['VANAGON_FORCE_SIGNING'] 41 | [] 42 | end 43 | end 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /lib/vanagon/utilities/shell_utilities.rb: -------------------------------------------------------------------------------- 1 | class Vanagon 2 | module Utilities 3 | module ShellUtilities 4 | module_function 5 | 6 | # join a combination of strings and arrays of strings into a single command 7 | # joined with '&&' 8 | # 9 | # @param commands [Array>] 10 | # @return [String] 11 | def andand(*commands) 12 | cmdjoin(commands, " && ") 13 | end 14 | 15 | # join a combination of strings and arrays of strings into a single command 16 | # joined with '&&' and broken up with newlines after each '&&' 17 | # 18 | # @param commands [Array>] 19 | # @return [String] 20 | def andand_multiline(*commands) 21 | cmdjoin(commands, " && \\\n") 22 | end 23 | 24 | def cmdjoin(commands, sep) 25 | commands.map { |o| Array(o) }.flatten.join(sep) 26 | end 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /resources/Makefile.erb: -------------------------------------------------------------------------------- 1 | SHELL = <%= @platform.shell %> 2 | 3 | <%- merged_environment.to_a(" := ").each do |var| -%> 4 | export <%= var %> 5 | <%- end -%> 6 | 7 | tempdir := $(shell <%= @platform.mktemp %> 2>/dev/null) 8 | workdir := $(PWD) 9 | 10 | all: file-list-before-build <%= package_name %> 11 | 12 | <%= package_name %>: <%= @name %>-<%= @version %>.tar.gz 13 | <%= generate_package.join("\n\t") %> 14 | 15 | file-list-before-build: 16 | <%- if dirnames.empty? -%> 17 | touch file-list-before-build 18 | <%- elsif @platform.is_windows? -%> 19 | (<%= @platform.find %> -H "<%= dirnames.map do |f| "$(shell cygpath -ml '#{f}')" end.join('" "') %>" 2>/dev/null || <%= @platform.find %> "<%= dirnames.map do |f| "$(shell cygpath -ml '#{f}')" end.join('" "') %>" 2>/dev/null) | <%= @platform.sort %> | uniq > file-list-before-build 20 | <%- else -%> 21 | (<%= @platform.find %> -H "<%= dirnames.join('" "') %>" 2>/dev/null || <%= @platform.find %> "<%= dirnames.join('" "') %>" 2>/dev/null) | <%= @platform.sort %> | uniq > file-list-before-build 22 | <%- end -%> 23 | 24 | file-list-after-build: <%= @components.map {|comp| comp.name }.join(" ") %> 25 | <%- if dirnames.empty? -%> 26 | touch file-list-after-build 27 | <%- elsif @platform.is_windows? -%> 28 | (<%= @platform.find %> -H "<%= dirnames.map do |f| "$(shell cygpath -ml '#{f}')" end.join('" "') %>" 2>/dev/null || <%= @platform.find %> "<%= dirnames.map do |f| "$(shell cygpath -ml '#{f}')" end.join('" "') %>" 2>/dev/null) | <%= @platform.sort %> | uniq > file-list-after-build 29 | <%- else -%> 30 | (<%= @platform.find %> -H "<%= dirnames.join('" "') %>" 2>/dev/null || <%= @platform.find %> "<%= dirnames.join('" "') %>" 2>/dev/null) | <%= @platform.sort %> | uniq > file-list-after-build 31 | <%- end -%> 32 | 33 | <%= @name %>-<%= @version %>.tar.gz: file-list <%= @cleanup ? 'cleanup-components' : '' %> 34 | <%= pack_tarball_command %> 35 | 36 | file-list: file-list-before-build <%= @name %>-project 37 | comm -23 file-list-after-build file-list-before-build > file-list 38 | comm -23 file-list-after-build file-list-before-build | <%= @platform.sed %> -e 's/\(^.*[[:space:]].*$$\)/"\1"/g' > file-list-for-rpm 39 | 40 | <%- if @version_file -%> 41 | <%= @version_file.path %>: 42 | echo <%= @version %> > '<%= @version_file.path %>' 43 | <%- end -%> 44 | 45 | <%- if @bill_of_materials -%> 46 | <%= @bill_of_materials.path %>: 47 | mkdir -p '<%= @bill_of_materials.path %>' 48 | mv bill-of-materials '<%= @bill_of_materials.path %>' 49 | <%- end -%> 50 | 51 | <%- dirnames.each do |dir| -%> 52 | <%= dir %>: file-list-before-build 53 | mkdir -p '<%= dir %>' 54 | <%- end %> 55 | 56 | <%- if @cleanup -%> 57 | cleanup-components: <%= @components.map {|comp| "#{comp.name}-cleanup" }.join(" ") %> 58 | touch cleanup-components 59 | <%- end -%> 60 | 61 | <%= @name %>-project: <%= dirnames.join(' ') %> <%= @version_file ? @version_file.path : '' %> <%= @bill_of_materials ? @bill_of_materials.path : '' %> file-list-after-build 62 | touch <%= @name %>-project 63 | 64 | <%- @components.each do |comp| -%> 65 | <%= comp.rules(self, @platform).to_s %> 66 | <%- end -%> 67 | 68 | clean: <%= @components.map {|comp| "#{comp.name}-clean" }.join(" ") %> 69 | 70 | clobber: <%= @components.map {|comp| "#{comp.name}-clobber" }.join(" ") %> 71 | 72 | .PHONY: clean clobber <%= @components.map {|comp| "#{comp.name}-clean #{comp.name}-clobber" }.join(" ") %> 73 | -------------------------------------------------------------------------------- /resources/deb/changelog.erb: -------------------------------------------------------------------------------- 1 | <%= @name %> (<%= @version %>-<%= @release %><%= @platform.codename %>) <%= @platform.codename %>; urgency=low 2 | 3 | * Update to version <%= @version %> 4 | 5 | -- <%= @vendor %> <%= Time.now.strftime("%a, %d %b %Y %H:%M:%S %z")%> 6 | -------------------------------------------------------------------------------- /resources/deb/conffiles.erb: -------------------------------------------------------------------------------- 1 | <%- get_configfiles.map {|file| file.path }.reject {|conf| conf.match(/^\/etc\//) }.each do |configfile| -%> 2 | <%= configfile %> 3 | <%- end -%> 4 | -------------------------------------------------------------------------------- /resources/deb/control.erb: -------------------------------------------------------------------------------- 1 | Source: <%= @name %> 2 | Maintainer: <%= @vendor %> 3 | Section: admin 4 | Priority: optional 5 | Build-Depends: debhelper (>= 7.0.0) 6 | Standards-Version: 3.9.1 7 | Homepage: <%= @homepage %> 8 | 9 | Package: <%= @name %> 10 | Architecture: <%= @noarch ? 'all' : 'any' %> 11 | Section: admin 12 | Priority: optional 13 | <%- unless get_replaces.empty? -%> 14 | Replaces: <%= get_replaces.map { |replace| "#{replace.replacement} #{replace.version ? "(#{replace.version})" : ""}" }.join(", ") %> 15 | Breaks: <%= get_replaces.map { |replace| "#{replace.replacement} #{replace.version ? "(#{replace.version})" : ""}" }.join(", ") %> 16 | <%- end -%> 17 | <%- unless get_conflicts.empty? -%> 18 | Conflicts: <%= get_conflicts.map { |conflict| "#{conflict.pkgname} #{conflict.version ? "(#{conflict.version})" : ""}" }.join(", ") %> 19 | <%- end -%> 20 | <%- unless get_requires.empty? -%> 21 | Depends: <%= get_requires.map { |req| "#{req.requirement} #{req.version ? "(#{req.version})" : ""}" }.join(", ") %> 22 | <%- end -%> 23 | <%- unless get_provides.empty? -%> 24 | Provides: <%= get_provides.map { |prov| prov.provide }.join(", ") %> 25 | <%- end -%> 26 | Description: <%= @description.lines.first.chomp %> 27 | <%= @description.lines[1..-1].join("\s") -%> 28 | . 29 | Contains the following components: 30 | <%= generate_bill_of_materials.join("\n\s") %> 31 | -------------------------------------------------------------------------------- /resources/deb/dirs.erb: -------------------------------------------------------------------------------- 1 | <%- get_directories.map {|d| d.path.sub(/^\//,'')}.each do |dir| -%> 2 | <%= dir %> 3 | <%- end -%> 4 | -------------------------------------------------------------------------------- /resources/deb/docs.erb: -------------------------------------------------------------------------------- 1 | <%- unless @bill_of_materials -%> 2 | bill-of-materials 3 | <%- end -%> 4 | -------------------------------------------------------------------------------- /resources/deb/install.erb: -------------------------------------------------------------------------------- 1 | <%- (get_files + get_configfiles).map {|f| f.path.sub(/^\//,'')}.each do |file| -%> 2 | <%= file %> 3 | <%- end -%> 4 | -------------------------------------------------------------------------------- /resources/deb/postinst.erb: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | <%- get_services.each do |service| -%> 3 | # switch based on systemd vs systemv 4 | # 5 | <%- if service.init_system.nil? || service.init_system.eql?('systemd') -%> 6 | if [ -f '/proc/1/comm' ]; then 7 | init_comm=`cat /proc/1/comm` 8 | if [ "$init_comm" = "systemd" ]; then 9 | if [ -z "$2" ]; then 10 | systemctl enable <%= service.name %>.service >/dev/null || : 11 | else 12 | systemctl try-restart <%= service.name %>.service >/dev/null || : 13 | fi 14 | fi 15 | fi 16 | <%- end -%> 17 | <%- if service.init_system.nil? || service.init_system.eql?('sysv') -%> 18 | if [ -f '/proc/1/comm' ]; then 19 | init_comm=`cat /proc/1/comm` 20 | if [ "$init_comm" = "init" ]; then 21 | if [ -x "<%= service.service_file %>" ]; then 22 | update-rc.d <%= service.name %> defaults > /dev/null 23 | 24 | if [ -n "$2" ]; then 25 | invoke-rc.d <%= service.name %> condrestart || true 26 | fi 27 | fi 28 | fi 29 | fi 30 | <%- end -%> 31 | <%- end -%> 32 | 33 | <%- if @user -%> 34 | # Add our user and group 35 | <%= @platform.add_group(@user) %> 36 | <%= @platform.add_user(@user) %> 37 | <%- end -%> 38 | 39 | # Set up any specific permissions needed... 40 | <%- (get_directories + get_configfiles + get_files).select { |pathname| pathname.has_overrides? }.uniq.each do |file_or_directory| -%> 41 | <%= "chmod '#{file_or_directory.mode}' '#{file_or_directory.path}' &>/dev/null ||:" if file_or_directory.mode %> 42 | <%- if file_or_directory.owner -%> 43 | if getent passwd '<%= file_or_directory.owner %>' &> /dev/null; then 44 | chown '<%= file_or_directory.owner %>' '<%= file_or_directory.path %>' &>/dev/null ||: 45 | else 46 | echo "Error updating '<%= file_or_directory.path %>': user '<%= file_or_directory.owner %>' does not exist." 47 | fi 48 | <%- end -%> 49 | <%- if file_or_directory.group -%> 50 | if getent group '<%= file_or_directory.group %>' &> /dev/null; then 51 | chgrp '<%= file_or_directory.group %>' '<%= file_or_directory.path %>' &>/dev/null ||: 52 | else 53 | echo "Error updating '<%= file_or_directory.path %>': group '<%= file_or_directory.group %>' does not exist." 54 | fi 55 | <%- end -%> 56 | <%- end -%> 57 | 58 | # Run trigger scripts on install if defined 59 | if [ $1 = triggered ] && [ -z $2 ]; then 60 | <%- get_interest_triggers("install").each do |trigger| -%> 61 | <%= trigger.scripts.join("\n") %> 62 | <%- end -%> 63 | : # no trigger scripts provided 64 | fi 65 | 66 | # Run trigger scripts on upgrade if defined 67 | if [ $1 = triggered ]&& [ -n $2 ]; then 68 | <%- get_interest_triggers("upgrade").each do |trigger| -%> 69 | <%= trigger.scripts.join("\n") %> 70 | <%- end -%> 71 | : # no trigger scripts provided 72 | fi 73 | 74 | 75 | # Run postinstall scripts on install if defined 76 | if [ $1 = configure ] && [ -z $2 ] ; then 77 | <%= get_postinstall_actions("install") %> 78 | fi 79 | 80 | # Run postinstall scripts on upgrade if defined 81 | if [ $1 = configure ] && [ -n $2 ] ; then 82 | <%= get_postinstall_actions("upgrade") %> 83 | fi 84 | -------------------------------------------------------------------------------- /resources/deb/postrm.erb: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Run post-removal scripts on upgrade if defined 4 | if [ $1 = upgrade ] && [ -n $2 ] ; then 5 | <%= get_postremove_actions("upgrade") %> 6 | fi 7 | 8 | # Run post-removal scripts on removal if defined 9 | if [ $1 = remove ] && [ -z $2 ] ; then 10 | <%= get_postremove_actions("removal") %> 11 | fi 12 | 13 | <%- get_services.each do |service| -%> 14 | # switch based on systemd vs systemv 15 | # 16 | if [ -f '/proc/1/comm' ]; then 17 | init_comm=`cat /proc/1/comm` 18 | if [ "$init_comm" = "systemd" ]; then 19 | systemctl daemon-reload >/dev/null 2>&1 || : 20 | else 21 | if [ "$1" = "purge" ] ; then 22 | update-rc.d <%= service.name %> remove > /dev/null 23 | fi 24 | fi 25 | fi 26 | <%- end -%> 27 | -------------------------------------------------------------------------------- /resources/deb/preinst.erb: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Run preinstall scripts on install if defined 4 | if [ $1 = install ] && [ -z $2 ] ; then 5 | <%= get_preinstall_actions("install") %> 6 | fi 7 | 8 | # Run preinstall scripts on upgrade if defined 9 | if [ $1 = upgrade ] && [ -n $2 ] ; then 10 | <%= get_preinstall_actions("upgrade") %> 11 | fi 12 | -------------------------------------------------------------------------------- /resources/deb/prerm.erb: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Run pre-removal scripts on upgrade if defined 4 | if [ $1 = upgrade ] && [ -n $2 ] ; then 5 | <%= get_preremove_actions("upgrade") %> 6 | fi 7 | 8 | # Run pre-removal scripts on removal if defined 9 | if [ $1 = remove ] && [ -z $2 ] ; then 10 | <%= get_preremove_actions("removal") %> 11 | fi 12 | 13 | <%- get_services.each do |service| -%> 14 | # switch based on systemd vs systemv 15 | # 16 | <%- if service.init_system.nil? || service.init_system.eql?('systemd') -%> 17 | if [ -f '/proc/1/comm' ]; then 18 | init_comm=`cat /proc/1/comm` 19 | if [ "$init_comm" = "systemd" ]; then 20 | if [ "$1" = remove ]; then 21 | systemctl --no-reload disable <%= service.name %>.service > /dev/null 2>&1 || : 22 | systemctl stop <%= service.name %>.service > /dev/null 2>&1 || : 23 | fi 24 | fi 25 | fi 26 | <%- end -%> 27 | <%- if service.init_system.nil? || service.init_system.eql?('sysv') -%> 28 | if [ -f '/proc/1/comm' ]; then 29 | init_comm=`cat /proc/1/comm` 30 | if [ "$init_comm" = "init" ]; then 31 | if [ -x "<%= service.service_file %>" ] && [ "$1" = remove ]; then 32 | invoke-rc.d <%= service.name %> stop || true 33 | fi 34 | fi 35 | fi 36 | <%- end -%> 37 | <%- end -%> 38 | -------------------------------------------------------------------------------- /resources/deb/rules.erb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # Uncomment this to turn on verbose mode. 3 | #export DH_VERBOSE=1 4 | 5 | <% @package_overrides.each do |var| %> 6 | <%= var %> 7 | <% end -%> 8 | 9 | override_dh_auto_install: 10 | install -d debian/tmp 11 | # Copy each directory into place 12 | <%- get_directories.map {|d| d.path.sub(/^\//,'')}.each do |dir| -%> 13 | if [ -d <%= dir %> ]; then \ 14 | install -d debian/tmp/<%= File.dirname(dir) %>; \ 15 | cp -pr <%= dir %> debian/tmp/<%= File.dirname(dir) %>; \ 16 | else \ 17 | install -d debian/tmp/<%= dir %>; \ 18 | fi 19 | <%- end -%> 20 | # Copy each of the extra files into place 21 | <%- (get_files + get_configfiles).map {|f| f.path.sub(/^\//,'')}.each do |file| -%> 22 | install -d debian/tmp/<%= File.dirname(file) %> 23 | cp -Rp <%= file %> debian/tmp/<%= File.dirname(file) %> 24 | <%- end -%> 25 | 26 | override_dh_shlibdeps: 27 | 28 | override_dh_usrlocal: 29 | 30 | override_dh_builddeb: 31 | # Force builddeb to use gzip for its internal compression. reprepro can get 32 | # confused if something newer is used. 33 | dh_builddeb -- -Zgzip 34 | 35 | %: 36 | dh $@ 37 | -------------------------------------------------------------------------------- /resources/deb/triggers.erb: -------------------------------------------------------------------------------- 1 | <%- get_activate_triggers.each do |trigger| -%> 2 | activate <%= trigger %> 3 | <% end -%> 4 | 5 | <%- get_interest_triggers("install").each do |trigger| -%> 6 | interest <%= trigger.interest_name %> 7 | <% end -%> 8 | 9 | <%- get_interest_triggers("upgrade").each do |trigger| -%> 10 | interest <%= trigger.interest_name %> 11 | <% end -%> 12 | -------------------------------------------------------------------------------- /resources/osx/postinstall.erb: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | <%- if has_configfiles? -%> 4 | # Move any new configfiles into place 5 | <%- get_configfiles.each do |config| 6 | dest_file = config.path.gsub(/\.pristine$/, '') -%> 7 | 8 | if [ -f "<%= dest_file %>" ]; then 9 | if diff "<%= config.path %>" "<%= dest_file %>" > /dev/null; then 10 | rm -f "<%= config.path %>" 11 | else 12 | echo "Detected file at '<%= dest_file %>'; updated file at '<%= config.path %>'." 13 | fi 14 | else 15 | mv '<%= config.path %>' '<%= dest_file %>' 16 | fi 17 | <%- end -%> 18 | <%- end -%> 19 | 20 | <%- if has_services? -%> 21 | if [ -d "/tmp/.<%= @name %>.upgrade" ]; then 22 | <%- get_services.each do |service| -%> 23 | if [ -f "/tmp/.<%= @name %>.upgrade/<%= service.name %>" ]; then 24 | /bin/launchctl load -F "<%= service.service_file %>" 25 | fi 26 | <%- end -%> 27 | fi 28 | <%- end -%> 29 | 30 | <%= File.read("resources/osx/postinstall-extras") if File.exist?("resources/osx/postinstall-extras") %> 31 | 32 | # Cleanup after ourselves 33 | if [ -e "/tmp/.<%= @name %>.upgrade" ]; then 34 | rm -rf "/tmp/.<%= @name %>.upgrade" 35 | fi 36 | -------------------------------------------------------------------------------- /resources/osx/preinstall.erb: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Cleanup previous operations 4 | if [ -e "/tmp/.<%= @name %>.upgrade" ]; then 5 | rm -rf "/tmp/.<%= @name %>.upgrade" 6 | fi 7 | 8 | # If we appear to be in an upgrade unload services. 9 | foundpkg=`/usr/sbin/pkgutil --volume "$3" --pkgs=<%= @identifier-%>.<%= @name -%>` 10 | oldbom="/usr/share/doc/<%= @name %>/bill-of-materials" 11 | 12 | if [ -n "$foundpkg" ]; then 13 | mkdir -p "/tmp/.<%= @name %>.upgrade" 14 | chmod 0700 "/tmp/.<%= @name %>.upgrade" 15 | 16 | <%- if has_services? -%> 17 | <%- get_services.each do |service| -%> 18 | if /bin/launchctl list "<%= service.name %>" &> /dev/null; then 19 | touch "/tmp/.<%= @name %>.upgrade/<%= service.name %>" 20 | /bin/launchctl unload "<%= service.service_file %>" 21 | fi 22 | if [ -f "$oldbom" ]; then 23 | /bin/rm "$oldbom" 24 | fi 25 | <%- end -%> 26 | <%- end -%> 27 | fi 28 | 29 | 30 | <%= File.read("resources/osx/preinstall-extras") if File.exist?("resources/osx/preinstall-extras") %> 31 | -------------------------------------------------------------------------------- /resources/osx/project-installer.xml.erb: -------------------------------------------------------------------------------- 1 | 2 | <%= @name -%> 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | <%= @name -%>-<%= @version -%>-<%= @release -%>.pkg 19 | 20 | -------------------------------------------------------------------------------- /resources/osx/uninstaller.tool.erb: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | <%- if has_services? -%> 4 | <%- get_services.each do |service| -%> 5 | echo "Unloading service <%= service.name %>..." 6 | /bin/launchctl unload <%= service.service_file %> 7 | echo "OK" 8 | echo "Removing service file <%= service.service_file %>..." 9 | /bin/rm <%= service.service_file %> 10 | echo "OK" 11 | <%- end -%> 12 | <%- end -%> 13 | 14 | echo "Removing identifier: <%= @identifier-%>.<%= @name -%>..." 15 | if /usr/sbin/pkgutil --files <%= @identifier-%>.<%= @name -%> >/dev/null 2>&1 ; then 16 | /usr/sbin/pkgutil --forget <%= @identifier-%>.<%= @name -%> 17 | 18 | fi 19 | echo "OK" 20 | 21 | echo "Removing Files" 22 | /bin/rm -Rf <%= get_directories.map {|d| d.path}.join(" ").to_s -%> 23 | 24 | echo "OK" 25 | -------------------------------------------------------------------------------- /resources/solaris/10/depend.erb: -------------------------------------------------------------------------------- 1 | <%- get_requires.each do |requires| -%> 2 | P <%= requires.requirement %> 3 | <%- end -%> 4 | -------------------------------------------------------------------------------- /resources/solaris/10/pkginfo.erb: -------------------------------------------------------------------------------- 1 | PKG="<%= @name %>" 2 | NAME="<%= @name %> - <%= @homepage %>" 3 | VERSION=<%= @version %>-<%= @release %> 4 | ARCH=<%= @noarch ? 'all' : @platform.architecture %> 5 | CLASSES=none 6 | CATEGORY=application 7 | VENDOR=<%= @vendor %> 8 | PSTAMP=<%= Time.now.strftime('%Y-%m-%d.%H%M%S') %> 9 | EMAIL=<%= vendor_email_only %> 10 | ISTATES=S s 1 2 3 11 | RSTATES=S s 1 2 3 12 | BASEDIR=/ 13 | 14 | -------------------------------------------------------------------------------- /resources/solaris/10/postinstall.erb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | <%- get_services.each do |service| -%> 4 | # Importing service <%= service.name %> 5 | /usr/sbin/svccfg import <%= service.service_file %> || true 6 | <%- end -%> 7 | 8 | # Move any new configfiles into place 9 | <%- get_configfiles.each do |config| 10 | dest_file = config.path.gsub(/\.pristine$/, '') -%> 11 | 12 | if [ -f "<%= dest_file %>" ]; then 13 | if diff "<%= config.path %>" "<%= dest_file %>" > /dev/null; then 14 | rm -f "<%= config.path %>" 15 | else 16 | echo "Detected file at '<%= dest_file %>'; updated file at '<%= config.path %>'." 17 | fi 18 | else 19 | cp -pr '<%= config.path %>' '<%= dest_file %>' 20 | fi 21 | 22 | <%- end -%> 23 | 24 | # Set up any specific permissions needed... 25 | <%- (get_directories + get_configfiles + get_files).select { |pathname| pathname.has_overrides? }.uniq.each do |file_or_directory| -%> 26 | <%- if file_or_directory.mode -%> 27 | if [ -f "<%= file_or_directory.path %>" ] || [ -d "<%= file_or_directory.path %>" ]; then 28 | chmod '<%= file_or_directory.mode %>' '<%= file_or_directory.path %>' 29 | fi 30 | <%- end -%> 31 | <%- if file_or_directory.owner -%> 32 | if getent passwd '<%= file_or_directory.owner %>' &> /dev/null; then 33 | chown '<%= file_or_directory.owner %>' '<%= file_or_directory.path %>' 34 | else 35 | echo "Error updating '<%= file_or_directory.path %>': user '<%= file_or_directory.owner %>' does not exist." 36 | fi 37 | <%- end -%> 38 | <%- if file_or_directory.group -%> 39 | if getent group '<%= file_or_directory.group %>' &> /dev/null; then 40 | chgrp '<%= file_or_directory.group %>' '<%= file_or_directory.path %>' 41 | else 42 | echo "Error updating '<%= file_or_directory.path %>': group '<%= file_or_directory.group %>' does not exist." 43 | fi 44 | <%- end -%> 45 | <%- end -%> 46 | 47 | <%- get_services.each do |service| -%> 48 | # Restarting service <%= service.name %> 49 | /usr/sbin/svcadm restart <%= service.name %> || true 50 | <%- end -%> 51 | -------------------------------------------------------------------------------- /resources/solaris/10/preinstall.erb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | # 3 | <%- if @user -%> 4 | # Add our user and group 5 | <%= @platform.add_group(@user) %> 6 | <%= @platform.add_user(@user) %> 7 | <%- end -%> 8 | -------------------------------------------------------------------------------- /resources/solaris/10/preremove.erb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | # 3 | <%- get_services.each do |service| -%> 4 | /usr/sbin/svcadm disable <%= service.name %> || true 5 | /usr/sbin/svccfg delete <%= service.name %> || true 6 | <%- end -%> 7 | -------------------------------------------------------------------------------- /resources/solaris/10/proto.erb: -------------------------------------------------------------------------------- 1 | i pkginfo=pkginfo 2 | i preinstall=preinstall 3 | i postinstall=postinstall 4 | i preremove=preremove 5 | i depend=depend 6 | -------------------------------------------------------------------------------- /resources/solaris/11/p5m.erb: -------------------------------------------------------------------------------- 1 | set name=pkg.fmri value="<%= @name %>@<%= @platform.ips_version(@version, @release) %>" 2 | set name=pkg.summary value="<%= @description.lines.first.chomp %>" 3 | set name=pkg.human-version value="<%= @version %>" 4 | set name=pkg.description value="<%= @description %>" 5 | set name=info.classification value="org.opensolaris.category.2008:System/Administration and Configuration" 6 | set name=org.opensolaris.consolidation value="<%= @name %>" 7 | set name=description value="<%= @description %>" 8 | set name=variant.opensolaris.zone value=global value=nonglobal 9 | <%- unless @noarch -%> 10 | set name=variant.arch value="<%= @platform.architecture %>" 11 | <%- end -%> 12 | 13 | <% 14 | def strip_and_escape(str) 15 | Regexp.escape(str.sub(/^\//, '')) 16 | end 17 | %> 18 | 19 | # Add any needed dependencies 20 | <%- get_requires.each do |requires| -%> 21 | depend fmri=pkg:/<%= requires.requirement %> type=require 22 | <%- end -%> 23 | 24 | # Always drop /etc, /usr, and /var, it will cause conflicts with other system packages 25 | drop> 26 | drop> 27 | drop> 28 | 29 | <%- get_root_directories.each do |dir| -%> 30 | $ -> drop> 31 | <%- end -%> 32 | 33 | <%- if has_services? -%> 34 | # Make sure smf manifests cause manifest-import to happen 35 | <%- get_services.each do |service| -%> 36 | $ -> default restart_fmri svc:/system/manifest-import:default> 37 | $ -> drop> 38 | <%- end -%> 39 | drop> 40 | set name=org.opensolaris.smf.fmri <%= get_services.map {|service| "value=svc:/#{service.type}/#{service.name}"}.join(" ") %> 41 | <%- end -%> 42 | 43 | <%- unless @bill_of_materials -%> 44 | # Move the bill-of-materials into a docdir for the package to avoid conflicts 45 | set path usr/share/doc/<%= @name %>/bill-of-materials> 46 | <%- end -%> 47 | 48 | <%- get_configfiles.each do |config| -%> 49 | # Preserve the old conf file on upgrade, restart services on config file change 50 | $ -> add preserve renamenew> 51 | <%- get_services.each do |service| -%> 52 | $ -> add restart_fmri <%= "svc:/#{service.type}/#{service.name}:*" %> > 53 | <%- end -%> 54 | <%- end -%> 55 | 56 | # Set any required owner, group or mode transformations 57 | <%- (get_configfiles + get_files).select { |pathname| pathname.has_overrides? }.uniq.each do |file| -%> 58 | <%- if file.group -%> 59 | $ -> set group <%= file.group %>> 60 | <%- end -%> 61 | <%- if file.owner -%> 62 | $ -> set owner <%= file.owner %>> 63 | <%- end -%> 64 | <%- if file.mode -%> 65 | $ -> set mode <%= file.mode %>> 66 | <%- end -%> 67 | <%- end -%> 68 | 69 | # Set any required owner, group or mode transformations 70 | <%- get_directories.select { |pathname| pathname.has_overrides? }.uniq.each do |dir| -%> 71 | <%- if dir.group -%> 72 | $ -> set group <%= dir.group %>> 73 | <%- end -%> 74 | <%- if dir.owner -%> 75 | $ -> set owner <%= dir.owner %>> 76 | <%- end -%> 77 | <%- if dir.mode -%> 78 | $ -> set mode <%= dir.mode %>> 79 | <%- end -%> 80 | <%- end -%> 81 | 82 | <%- if @user -%> 83 | # Create a user/group if desired 84 | <%= @platform.add_group(@user) %> 85 | <%= @platform.add_user(@user) %> 86 | <%- end -%> 87 | -------------------------------------------------------------------------------- /resources/windows/nuget/chocolateyInstall.ps1: -------------------------------------------------------------------------------- 1 | $toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)" 2 | $fileList = Join-Path -path $toolsDir -childpath "file-list.txt" 3 | 4 | if (!(Test-Path -path "$fileList")) { 5 | Throw "Unable to find file '$fileList', cannot proceed with install" 6 | } 7 | 8 | $lines = Get-Content "$fileList" 9 | foreach ($destination in $lines) { 10 | $originFile = "$destination" -replace '^[a-zA-Z]:/','' 11 | $origin = Join-Path -path "$toolsDir" -childpath "$originFile" 12 | if (Test-Path -path "$origin") { 13 | $parent = Split-Path -path "$destination" -parent 14 | if (!(Test-Path -path "$parent")) { 15 | New-Item -ItemType directory -Path "$parent" 16 | } 17 | if (Test-Path -path "$destination") { 18 | Write-Debug "Overwriting '$destination'" 19 | } 20 | Copy-Item -path "$origin" -destination "$destination" -Force 21 | } else { 22 | # If the item we are trying to copy over does not exist in our source directory, 23 | # we assume it is an empty directory and simply create one in its place. There is 24 | # a possibility that this will hide an error where there is actually a missing 25 | # file. However, this is such a slim possibity, this action was deemed safe. 26 | if (Test-Path -path "$destination") { 27 | if (Test-Path -path "$destination" -pathType container) { 28 | Write-Debug "Directory '$destination' already exists" 29 | } else { 30 | Throw "File '$destination' exists and is not a directory, cannot proceed with install" 31 | } 32 | } else { 33 | New-Item -ItemType directory -Path "$destination" 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /resources/windows/nuget/chocolateyUninstall.ps1: -------------------------------------------------------------------------------- 1 | $toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)" 2 | $fileList = Join-Path -path $toolsDir -childpath "file-list.txt" 3 | 4 | if (!(Test-Path -path "$fileList")) { 5 | Throw "Unable to find file '$fileList', cannot proceed with uninstall" 6 | } 7 | 8 | $lines = Get-Content "$fileList" 9 | foreach ($file in $lines) { 10 | if (Test-Path -path "$file") { 11 | # We cannot guarentee a directory is only populated with files from 12 | # this package, so we cannot whole-sale remove directories. We could 13 | # check to see if a directory is empty after we remove all the files, 14 | # but that would still end up with some reminantes of our skeletal 15 | # directory structure. It doesn't seem worth it ATM. As is, only remove 16 | # things that are files, and do not remove any directories. 17 | if (!((Get-Item "$file") -is [System.IO.DirectoryInfo])) { 18 | Write-Debug "Removing '$file'" 19 | remove-item -Path "$file" -Force 20 | } 21 | } else { 22 | Write-Debug "Skipping missing file '$file'" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /resources/windows/nuget/project.nuspec.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= "#{@name}-#{@platform.architecture}" %> 5 | <%= @platform.nuget_package_version(@version, @release) %> 6 | <%= @name %> 7 | <%= vendor_name_only %> 8 | <%= vendor_name_only %> 9 | <%= @homepage %> 10 | <%= @homepage %> 11 | <%= @homepage %> 12 | <%= @homepage %> 13 | <%= @homepage %> 14 | <%= @homepage %> 15 | <%= @homepage %> 16 | false 17 | 18 | <%= @description %> 19 | 20 | <%= @description.lines.first.chomp %> 21 | <%= @homepage %> 22 | <%= vendor_name_only %> 23 | puppet configuration management infrastructure automation facter hiera mco mcollective marionette collective 24 | <%= get_replaces.map { |replace| "#{replace.replacement}" }.join(" ") %> 25 | <%= get_replaces.map { |replace| "#{replace.replacement}" }.join(" ") %> 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /resources/windows/wix/directorylist.wxs.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= @platform.generate_service_bin_dirs(self.get_services, self) %> 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /resources/windows/wix/filter.xslt.erb: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | <%- service_files = Array.new -%> 22 | <%- get_services.each do |service| -%> 23 | 24 | <%- service_files << service.service_file.sub("SourceDir\\#{self.settings[:base_dir]}\\#{self.settings[:company_id]}\\#{self.settings[:product_id]}", "$(var.AppSourcePath)") -%> 25 | <%- end -%> 26 | <%- service_files.uniq.each do |service_file| -%> 27 | 28 | <%- end -%> 29 | 30 | -------------------------------------------------------------------------------- /spec/fixtures/component/invalid-test-fixture.json: -------------------------------------------------------------------------------- 1 | { 2 | "thing": "stuff" 3 | } 4 | -------------------------------------------------------------------------------- /spec/fixtures/component/mcollective.service: -------------------------------------------------------------------------------- 1 | /opt/puppetlabs/puppet/bin/ruby -s mcollective -u root -a '/opt/puppetlabs/puppet/bin/mcollectived --config=/etc/puppetlabs/mcollective/server.cfg ' 2 | -------------------------------------------------------------------------------- /spec/fixtures/component/test-fixture.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "git@github.com:puppetlabs/puppet", 3 | "ref": "3.7.3" 4 | } 5 | -------------------------------------------------------------------------------- /spec/fixtures/files/fake_dir.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_dir.tar.gz -------------------------------------------------------------------------------- /spec/fixtures/files/fake_dir/fake_file.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_dir/fake_file.txt -------------------------------------------------------------------------------- /spec/fixtures/files/fake_file.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_file.txt -------------------------------------------------------------------------------- /spec/fixtures/files/fake_file.txt.erb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_file.txt.erb -------------------------------------------------------------------------------- /spec/fixtures/files/fake_file_ext.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_file_ext.7z -------------------------------------------------------------------------------- /spec/fixtures/files/fake_file_ext.bz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_file_ext.bz -------------------------------------------------------------------------------- /spec/fixtures/files/fake_file_ext.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_file_ext.bz2 -------------------------------------------------------------------------------- /spec/fixtures/files/fake_file_ext.cpio: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_file_ext.cpio -------------------------------------------------------------------------------- /spec/fixtures/files/fake_file_ext.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_file_ext.gz -------------------------------------------------------------------------------- /spec/fixtures/files/fake_file_ext.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_file_ext.rar -------------------------------------------------------------------------------- /spec/fixtures/files/fake_file_ext.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_file_ext.tar -------------------------------------------------------------------------------- /spec/fixtures/files/fake_file_ext.tar.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_file_ext.tar.bz2 -------------------------------------------------------------------------------- /spec/fixtures/files/fake_file_ext.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_file_ext.tar.gz -------------------------------------------------------------------------------- /spec/fixtures/files/fake_file_ext.tar.xz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_file_ext.tar.xz -------------------------------------------------------------------------------- /spec/fixtures/files/fake_file_ext.tbz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_file_ext.tbz -------------------------------------------------------------------------------- /spec/fixtures/files/fake_file_ext.tbz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_file_ext.tbz2 -------------------------------------------------------------------------------- /spec/fixtures/files/fake_file_ext.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_file_ext.tgz -------------------------------------------------------------------------------- /spec/fixtures/files/fake_file_ext.txz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_file_ext.txz -------------------------------------------------------------------------------- /spec/fixtures/files/fake_file_ext.xz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_file_ext.xz -------------------------------------------------------------------------------- /spec/fixtures/files/fake_file_ext.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_file_ext.z -------------------------------------------------------------------------------- /spec/fixtures/files/fake_file_ext.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_file_ext.zip -------------------------------------------------------------------------------- /spec/fixtures/files/fake_nested_dir/fake_dir/fake_file.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/files/fake_nested_dir/fake_dir/fake_file.txt -------------------------------------------------------------------------------- /spec/fixtures/wix/resources/windows/wix/file-1.wxs: -------------------------------------------------------------------------------- 1 | # Wix Test File 1 2 | -------------------------------------------------------------------------------- /spec/fixtures/wix/resources/windows/wix/file-2.wxs: -------------------------------------------------------------------------------- 1 | # Wix Test File 2 2 | -------------------------------------------------------------------------------- /spec/fixtures/wix/resources/windows/wix/file-3.wxs.erb: -------------------------------------------------------------------------------- 1 | # ERB Wix Test File 3 2 | -------------------------------------------------------------------------------- /spec/fixtures/wix/resources/windows/wix/file-4.wxs.erb: -------------------------------------------------------------------------------- 1 | # ERB Wix Test File 4 2 | -------------------------------------------------------------------------------- /spec/fixtures/wix/resources/windows/wix/include/include-sample-1.wxs: -------------------------------------------------------------------------------- 1 | # Sample Include file 2 | -------------------------------------------------------------------------------- /spec/fixtures/wix/resources/windows/wix/project.filter.xslt.erb: -------------------------------------------------------------------------------- 1 | # Null ERB File for testing 2 | -------------------------------------------------------------------------------- /spec/fixtures/wix/resources/windows/wix/project.wxs: -------------------------------------------------------------------------------- 1 | # Test file for Vanagon/Wix unit testing. 2 | # This file will "over-ride" the generic Product.wix.erb file 3 | -------------------------------------------------------------------------------- /spec/fixtures/wix/resources/windows/wix/ui/bitmaps/bitmap.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/vanagon/701cccd065d8ebac128fe262873c94020be983db/spec/fixtures/wix/resources/windows/wix/ui/bitmaps/bitmap.bmp -------------------------------------------------------------------------------- /spec/fixtures/wix/resources/windows/wix/ui/ui-sample-1.wxs: -------------------------------------------------------------------------------- 1 | # This is a sample UI wxs file 2 | -------------------------------------------------------------------------------- /spec/lib/git/rev_list_spec.rb: -------------------------------------------------------------------------------- 1 | require 'git/rev_list' 2 | include LibRevList 3 | 4 | describe 'Git::LibRevList' do 5 | describe '#rev_list' do 6 | it 'calls command' do 7 | expect(LibRevList).to receive(:command).with('rev-list', []) 8 | LibRevList.rev_list 9 | end 10 | 11 | it 'calls command with commitish' do 12 | expect(LibRevList).to receive(:command).with('rev-list', ['HEAD']) 13 | LibRevList.rev_list('HEAD') 14 | end 15 | 16 | it 'calls command with commitish and a boolean option' do 17 | expect(LibRevList).to receive(:command).with('rev-list', ['--count', 'HEAD']) 18 | LibRevList.rev_list('HEAD', { :count => true }) 19 | end 20 | 21 | it 'calls command with commitish and an option that uses a param' do 22 | expect(LibRevList).to receive(:command).with('rev-list', ['--max-age=200', 'HEAD']) 23 | LibRevList.rev_list('HEAD', { :max_age => 200 }) 24 | end 25 | end 26 | end -------------------------------------------------------------------------------- /spec/lib/makefile_spec.rb: -------------------------------------------------------------------------------- 1 | require 'makefile' 2 | 3 | describe Makefile::Rule do 4 | describe "a rule with no dependencies and an empty recipe" do 5 | subject { described_class.new("empty") } 6 | 7 | it "creates an empty rule" do 8 | expect(subject.format).to eq "empty:\n" 9 | end 10 | end 11 | 12 | describe "a rule with no dependencies and a simple recipe" do 13 | subject { described_class.new("simple", recipe: ["touch simple"]) } 14 | 15 | it "creates the rule with the recipe" do 16 | expect(subject.format).to eq "simple:\n\ttouch simple\n" 17 | end 18 | end 19 | 20 | describe "a rule with dependencies and no recipe" do 21 | subject { described_class.new("depends", dependencies: ["mydeps"]) } 22 | 23 | it "creates the rule with the recipe" do 24 | expect(subject.format).to eq "depends: mydeps\n" 25 | end 26 | end 27 | 28 | describe "a rule with dependencies and a recipe" do 29 | subject { described_class.new("deluxe", recipe: ["touch deluxe"], dependencies: ["mydeps"]) } 30 | 31 | it "creates the rule with the recipe" do 32 | expect(subject.format).to eq "deluxe: mydeps\n\ttouch deluxe\n" 33 | end 34 | end 35 | 36 | describe "a rule with a multiline recipe" do 37 | subject do 38 | described_class.new("multiline") do |rule| 39 | rule.recipe = [ 40 | "[ -d build ] || mkdir -p build", 41 | "cd build &&\ncmake .. &&\nmake &&\nmake install" 42 | ] 43 | end 44 | end 45 | 46 | it "inserts tabs after each newline in the recipe" do 47 | expect(subject.format).to eq "multiline:\n\t[ -d build ] || mkdir -p build\n\tcd build &&\n\tcmake .. &&\n\tmake &&\n\tmake install\n" 48 | end 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /spec/lib/vanagon/common/pathname_spec.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/common/pathname' 2 | 3 | describe "Vanagon::Common::Pathname" do 4 | describe "#has_overrides?" do 5 | it "is false for a pathname with just a path" do 6 | dir = Vanagon::Common::Pathname.new("/a/b/c") 7 | expect(dir.has_overrides?).to be(false) 8 | end 9 | 10 | it "is true if the pathname has more than a path set" do 11 | dir = Vanagon::Common::Pathname.new("/a/b/c", mode: '0755') 12 | expect(dir.has_overrides?).to be(true) 13 | end 14 | end 15 | 16 | describe "#file" do 17 | it 'creates a new Pathname instance, marked as a file' do 18 | dir = Vanagon::Common::Pathname.file("/a/b/c/") 19 | expect(dir.class).to eq(Vanagon::Common::Pathname) 20 | expect(dir.configfile?).to eq(false) 21 | end 22 | end 23 | 24 | describe "#configfile" do 25 | it 'creates a new Pathname instance, marked as a configuration file' do 26 | dir = Vanagon::Common::Pathname.configfile("/a/b/c/") 27 | expect(dir.class).to eq(Vanagon::Common::Pathname) 28 | expect(dir.configfile?).to eq(true) 29 | end 30 | end 31 | 32 | describe "#initialize" do 33 | it 'strips trailing slashes off of the path to normalize it' do 34 | dir = Vanagon::Common::Pathname.new("/a/b/c/") 35 | expect(dir.path).to eq("/a/b/c") 36 | end 37 | 38 | it 'removes extra / from the pathname to normalize it' do 39 | dir = Vanagon::Common::Pathname.new("/a//b///c///") 40 | expect(dir.path).to eq("/a/b/c") 41 | end 42 | end 43 | 44 | describe "equality" do 45 | it "is not equal if the paths differ" do 46 | dir1 = Vanagon::Common::Pathname.new("/a/b/c") 47 | dir2 = Vanagon::Common::Pathname.new("/a/b/c/d") 48 | expect(dir1).not_to eq(dir2) 49 | end 50 | 51 | it "is not equal if there are different attributes set" do 52 | dir1 = Vanagon::Common::Pathname.new("/a/b/c") 53 | dir2 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123') 54 | expect(dir1).not_to eq(dir2) 55 | end 56 | 57 | it "is equal if there are the same attributes set to the same values" do 58 | dir1 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123') 59 | dir2 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123') 60 | expect(dir1).to eq(dir2) 61 | end 62 | 63 | it "is equal if the paths are the same and the only attribute set" do 64 | dir1 = Vanagon::Common::Pathname.new("/a/b/c") 65 | dir2 = Vanagon::Common::Pathname.new("/a/b/c") 66 | expect(dir1).to eq(dir2) 67 | end 68 | end 69 | 70 | describe "#hash" do 71 | it "has the same hash is the attributes are the same" do 72 | dir1 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123') 73 | dir2 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123') 74 | expect(dir1.hash).to eq(dir2.hash) 75 | end 76 | 77 | it "has different hashes if any attribute is different" do 78 | dir1 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123', owner: 'alice') 79 | dir2 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123', owner: 'bob') 80 | expect(dir1.hash).to_not eq(dir2.hash) 81 | end 82 | end 83 | 84 | describe "uniqueness of pathnames" do 85 | it "should only add 1 Pathname object with the same attributes to a set" do 86 | set = Set.new 87 | dir1 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123') 88 | dir2 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123') 89 | dir3 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123', owner: 'alice') 90 | set << dir1 << dir2 << dir3 91 | expect(set.size).to eq(2) 92 | end 93 | 94 | it "should reduce an array to unique elements successfully" do 95 | dir1 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123') 96 | dir2 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123') 97 | dir3 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123', owner: 'alice') 98 | arr = [ dir1, dir2, dir3 ] 99 | expect(arr.size).to eq(3) 100 | expect(arr.uniq.size).to eq(2) 101 | end 102 | end 103 | end 104 | -------------------------------------------------------------------------------- /spec/lib/vanagon/common/user_spec.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/common/user' 2 | 3 | describe 'Vanagon::Common::User' do 4 | describe 'initialize' do 5 | it 'group defaults to the name of the user' do 6 | user = Vanagon::Common::User.new('willamette') 7 | expect(user.group).to eq('willamette') 8 | end 9 | end 10 | 11 | describe 'equality' do 12 | it 'is not equal if the names differ' do 13 | user1 = Vanagon::Common::User.new('willamette') 14 | user2 = Vanagon::Common::User.new('columbia') 15 | expect(user1).not_to eq(user2) 16 | end 17 | 18 | it 'is not equal if there are different attributes set' do 19 | user1 = Vanagon::Common::User.new('willamette', 'group1') 20 | user2 = Vanagon::Common::User.new('willamette', 'group2') 21 | expect(user1).not_to eq(user2) 22 | end 23 | 24 | it 'is equal if there are the same attributes set to the same values' do 25 | user1 = Vanagon::Common::User.new('willamette', 'group') 26 | user2 = Vanagon::Common::User.new('willamette', 'group') 27 | expect(user1).to eq(user2) 28 | end 29 | 30 | it 'is equal if the name are the same and the only attribute set' do 31 | user1 = Vanagon::Common::User.new('willamette') 32 | user2 = Vanagon::Common::User.new('willamette') 33 | expect(user1).to eq(user2) 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /spec/lib/vanagon/component/source/http_spec.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/component/source/git' 2 | 3 | describe "Vanagon::Component::Source::Http" do 4 | let (:base_url) { 'https://artifactory.delivery.puppetlabs.net/artifactory/generic/buildsources/' } 5 | let (:file_base) { 'thing-1.2.3' } 6 | let (:tar_filename) { 'thing-1.2.3.tar.gz' } 7 | let (:tar_url) { "#{base_url}/#{tar_filename}" } 8 | let (:tar_dirname) { 'thing-1.2.3' } 9 | let (:plaintext_filename) { 'thing-1.2.3.txt' } 10 | let (:plaintext_url) { "#{base_url}/#{plaintext_filename}" } 11 | let (:plaintext_dirname) { './' } 12 | let (:md5sum) { 'abcdssasasa' } 13 | let (:sha256sum) { 'foobarbaz' } 14 | let (:sha512sum) { 'teststring' } 15 | let (:workdir) { Dir.mktmpdir } 16 | 17 | describe "#initialize" do 18 | it "fails with a bad sum_type" do 19 | expect { Vanagon::Component::Source::Http.new(plaintext_url, sum: md5sum, workdir: workdir, sum_type: "md4") } 20 | .to raise_error(RuntimeError) 21 | end 22 | end 23 | 24 | describe "#dirname" do 25 | it "returns the name of the tarball, minus extension for archives" do 26 | http_source = Vanagon::Component::Source::Http.new(tar_url, sum: md5sum, workdir: workdir, sum_type: "md5") 27 | expect(http_source).to receive(:download).and_return(tar_filename) 28 | http_source.fetch 29 | expect(http_source.dirname).to eq(tar_dirname) 30 | end 31 | 32 | it "returns the current directory for non-archive files" do 33 | http_source = Vanagon::Component::Source::Http.new(plaintext_url, sum: md5sum, workdir: workdir, sum_type: "md5") 34 | expect(http_source).to receive(:download).and_return(plaintext_filename) 35 | http_source.fetch 36 | expect(http_source.dirname).to eq(plaintext_dirname) 37 | end 38 | end 39 | 40 | describe "#verify" do 41 | it "calls md5 digest when it's supposed to" do 42 | allow_any_instance_of(Digest::MD5).to receive(:file).and_return(Digest::MD5.new) 43 | allow_any_instance_of(Digest::MD5).to receive(:hexdigest).and_return(md5sum) 44 | http_source = Vanagon::Component::Source::Http.new(plaintext_url, sum: md5sum, workdir: workdir, sum_type: "md5") 45 | expect(http_source).to receive(:download).and_return(plaintext_filename) 46 | http_source.fetch 47 | http_source.verify 48 | end 49 | 50 | it "calls sha256 digest when it's supposed to" do 51 | allow_any_instance_of(Digest::SHA256).to receive(:file).and_return(Digest::SHA256.new) 52 | allow_any_instance_of(Digest::SHA256).to receive(:hexdigest).and_return(sha256sum) 53 | http_source = Vanagon::Component::Source::Http.new(plaintext_url, sum: sha256sum, workdir: workdir, sum_type: "sha256") 54 | expect(http_source).to receive(:download).and_return(plaintext_filename) 55 | http_source.fetch 56 | http_source.verify 57 | end 58 | 59 | it "calls sha512 digest when it's supposed to" do 60 | allow_any_instance_of(Digest::SHA512).to receive(:file).and_return(Digest::SHA512.new) 61 | allow_any_instance_of(Digest::SHA512).to receive(:hexdigest).and_return(sha512sum) 62 | http_source = Vanagon::Component::Source::Http.new(plaintext_url, sum: sha512sum, workdir: workdir, sum_type: "sha512") 63 | expect(http_source).to receive(:download).and_return(plaintext_filename) 64 | http_source.fetch 65 | http_source.verify 66 | end 67 | end 68 | end 69 | -------------------------------------------------------------------------------- /spec/lib/vanagon/component/source/local_spec.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/component/source/git' 2 | 3 | describe "Vanagon::Component::Source::File" do 4 | let (:file_base) { 'file://spec/fixtures/files/fake_file_ext' } 5 | let (:tar_filename) { 'file://spec/fixtures/files/fake_dir.tar.gz' } 6 | let (:plaintext_filename) { 'file://spec/fixtures/files/fake_file.txt' } 7 | let (:workdir) { Dir.mktmpdir } 8 | let (:simple_directory) { 'file://spec/fixtures/files/fake_dir/' } 9 | let (:nested_directory) { 'file://spec/fixtures/files/fake_nested_dir/' } 10 | 11 | describe "#fetch" do 12 | it "puts the source file in to the workdir" do 13 | file = Vanagon::Component::Source::Local.new(plaintext_filename, workdir: workdir) 14 | file.fetch 15 | expect(File).to exist("#{workdir}/fake_file.txt") 16 | end 17 | 18 | it "puts the source directory in to the workdir" do 19 | file = Vanagon::Component::Source::Local.new(simple_directory, workdir: workdir) 20 | file.fetch 21 | expect(File).to exist("#{workdir}/fake_dir/fake_file.txt") 22 | end 23 | 24 | it "preserves nested directories when copying folders" do 25 | file = Vanagon::Component::Source::Local.new(nested_directory, workdir: workdir) 26 | file.fetch 27 | expect(File).to exist("#{workdir}/fake_nested_dir/fake_dir/fake_file.txt") 28 | end 29 | end 30 | 31 | describe "#dirname" do 32 | it "returns the name of the tarball, minus extension for archives" do 33 | file = Vanagon::Component::Source::Local.new(tar_filename, workdir: workdir) 34 | file.fetch 35 | expect(file.dirname).to eq("fake_dir") 36 | end 37 | end 38 | 39 | describe "#ref" do 40 | it "returns the current directory for non-archive files" do 41 | file = Vanagon::Component::Source::Local.new(plaintext_filename, workdir: workdir) 42 | file.fetch 43 | expect(file.dirname).to eq("./") 44 | end 45 | end 46 | 47 | describe "#extension" do 48 | it "returns the extension for valid extensions" do 49 | Vanagon::Component::Source::Local.archive_extensions.each do |ext| 50 | filename = "#{file_base}#{ext}" 51 | file = Vanagon::Component::Source::Local.new(filename, workdir: workdir) 52 | file.fetch 53 | expect(file.extension).to eq(ext) 54 | end 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /spec/lib/vanagon/component/source/rewrite_spec.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/component/source' 2 | 3 | describe "Vanagon::Component::Source::Rewrite" do 4 | let(:klass) { Vanagon::Component::Source::Rewrite } 5 | let(:artifactory_url) { "https://artifactory.delivery.puppetlabs.net/artifactory" } 6 | let(:buildsources_url) { "#{artifactory_url}/generic/buildsources" } 7 | before(:each) { klass.rewrite_rules.clear } 8 | 9 | describe ".parse_and_rewrite" do 10 | let(:simple_rule) { Proc.new {|url| url.gsub('a', 'e') } } 11 | let(:complex_rule) do 12 | Proc.new do |url| 13 | match = url.match(/github.com\/(.*)$/) 14 | "git://github.delivery.puppetlabs.net/#{match[1].gsub('/', '-')}" if match 15 | end 16 | end 17 | 18 | it 'replaces the first section of a url with a string if string is given' do 19 | klass.register_rewrite_rule('http', buildsources_url) 20 | 21 | expect(klass.rewrite('http://things.and.stuff/foo.tar.gz', 'http')) 22 | .to eq("#{buildsources_url}/foo.tar.gz") 23 | end 24 | 25 | it 'applies the rule to the url if a proc is given as the rule' do 26 | klass.register_rewrite_rule('http', simple_rule) 27 | 28 | expect(klass.rewrite('http://things.and.stuff/foo.tar.gz', 'http')) 29 | .to eq('http://things.end.stuff/foo.ter.gz') 30 | end 31 | 32 | it 'applies the rule to the url if a proc is given as the rule' do 33 | klass.register_rewrite_rule('git', complex_rule) 34 | 35 | expect(klass.rewrite('git://github.com/puppetlabs/facter', 'git')) 36 | .to eq('git://github.delivery.puppetlabs.net/puppetlabs-facter') 37 | end 38 | end 39 | 40 | describe ".register_rewrite_rule" do 41 | it 'only accepts Proc and String as rule types' do 42 | expect { klass.register_rewrite_rule('http', 5) } 43 | .to raise_error(Vanagon::Error) 44 | end 45 | 46 | it 'rejects invalid protocols' do 47 | expect { klass.register_rewrite_rule('gopher', 'abcd') } 48 | .to raise_error Vanagon::Error 49 | end 50 | 51 | before { klass.register_rewrite_rule('http', buildsources_url) } 52 | it 'registers the rule for the given protocol' do 53 | expect(klass.rewrite_rules) 54 | .to eq({'http' => buildsources_url}) 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /spec/lib/vanagon/engine/base_spec.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/engine/base' 2 | 3 | describe 'Vanagon::Engine::Base' do 4 | let (:platform_without_ssh_port) { 5 | plat = Vanagon::Platform::DSL.new('debian-6-i386') 6 | plat.instance_eval("platform 'debian-6-i386' do |plat| 7 | plat.ssh_port nil 8 | end") 9 | plat._platform 10 | } 11 | 12 | let (:platform) { 13 | plat = Vanagon::Platform::DSL.new('debian-6-i386') 14 | plat.instance_eval("platform 'debian-6-i386' do |plat| 15 | end") 16 | plat._platform 17 | } 18 | 19 | describe '#select_target' do 20 | it 'raises an error without a target' do 21 | base = Vanagon::Engine::Base.new(platform) 22 | expect { base.select_target }.to raise_error(Vanagon::Error) 23 | end 24 | 25 | it 'returns a target if one is set' do 26 | base = Vanagon::Engine::Base.new(platform, 'abcd') 27 | expect(base.select_target).to eq('abcd') 28 | end 29 | end 30 | 31 | describe '#validate_platform' do 32 | it 'raises an error if the platform is missing a required attribute' do 33 | expect{ Vanagon::Engine::Base.new(platform_without_ssh_port).validate_platform }.to raise_error(Vanagon::Error) 34 | end 35 | 36 | it 'returns true if the platform has the required attributes' do 37 | expect(Vanagon::Engine::Base.new(platform).validate_platform).to be(true) 38 | end 39 | end 40 | 41 | describe "#retrieve_built_artifact" do 42 | it 'creates a new output dir' do 43 | base = Vanagon::Engine::Base.new(platform) 44 | allow(Vanagon::Utilities).to receive(:rsync_from) 45 | expect(FileUtils).to receive(:mkdir_p) 46 | base.retrieve_built_artifact([], false) 47 | end 48 | 49 | it 'rsync uses normal output dir when no_package param is false' do 50 | base = Vanagon::Engine::Base.new(platform, 'abcd') 51 | allow(FileUtils).to receive(:mkdir_p) 52 | expect(Vanagon::Utilities).to receive(:rsync_from).with('/output/*', 'root@abcd', 'output/', 22) 53 | base.retrieve_built_artifact([], false) 54 | end 55 | 56 | it 'rsync only contents of parameter if no_package is true' do 57 | base = Vanagon::Engine::Base.new(platform, 'abcd') 58 | allow(FileUtils).to receive(:mkdir_p) 59 | expect(Vanagon::Utilities).to receive(:rsync_from).with('foo/bar/baz.file', 'root@abcd', 'output/', 22) 60 | base.retrieve_built_artifact(['foo/bar/baz.file'], true) 61 | end 62 | 63 | it 'rsync only contents of parameter with multiple entries if no_package param is true' do 64 | base = Vanagon::Engine::Base.new(platform, 'abcd') 65 | allow(FileUtils).to receive(:mkdir_p) 66 | expect(Vanagon::Utilities).to receive(:rsync_from).with('foo/bar/baz.file', 'root@abcd', 'output/', 22) 67 | expect(Vanagon::Utilities).to receive(:rsync_from).with('foo/foobar/foobarbaz.file', 'root@abcd', 'output/', 22) 68 | base.retrieve_built_artifact(['foo/bar/baz.file', 'foo/foobar/foobarbaz.file'], true) 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /spec/lib/vanagon/engine/ec2_spec.rb: -------------------------------------------------------------------------------- 1 | begin 2 | require 'aws-sdk' 3 | 4 | rescue LoadError 5 | STDERR.puts "Unable to load AWS SDK; skipping optional EC2 engine spec tests" 6 | end 7 | 8 | if defined? Aws 9 | require 'vanagon/engine/ec2' 10 | require 'vanagon/platform' 11 | 12 | describe 'Vanagon::Engine::Ec2' do 13 | let(:platform_ec2) do 14 | plat = Vanagon::Platform::DSL.new('el-7-x86_64') 15 | plat.instance_eval(<<-END) 16 | platform 'el-7-x86_64' do |plat| 17 | plat.aws_ami 'ami' 18 | plat.target_user 'root' 19 | plat.aws_subnet_id 'subnet_id' 20 | plat.aws_user_data 'user_data' 21 | plat.aws_region 'us-west-1' 22 | plat.aws_key_name 'vanagon' 23 | plat.aws_instance_type 't1.micro' 24 | plat.ssh_port '22' 25 | end 26 | END 27 | plat._platform 28 | end 29 | 30 | it 'returns "ec2" name' do 31 | stub_request(:get, "http://169.254.169.254/latest/meta-data/iam/security-credentials/"). 32 | to_return(status: 200, body: "", headers: {}) 33 | stub_request(:put, "http://169.254.169.254/latest/api/token"). 34 | to_return(status: 200, body: "", headers: {}) 35 | 36 | ## This fails with 37 | ## MultiFactorAuthentication failed, must provide both MFA serial number 38 | ## and one time pass code. 39 | ## Remove until is can be properly repaired/mocked/etc. 40 | 41 | # expect(Vanagon::Engine::Ec2.new(platform_ec2).name).to eq('ec2') 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /spec/lib/vanagon/engine/hardware_spec.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/engine/hardware' 2 | require 'vanagon/driver' 3 | require 'vanagon/platform' 4 | require 'logger' 5 | 6 | # Haus, I added this, cause it prevented errors. 7 | class Vanagon 8 | class Driver 9 | @@logger = Logger.new('/dev/null') 10 | end 11 | end 12 | 13 | describe 'Vanagon::Engine::Hardware' do 14 | 15 | let (:platform_without_build_hosts) { 16 | plat = Vanagon::Platform::DSL.new('aix-7.1-ppc') 17 | plat.instance_eval("platform 'aix-7.1-ppc' do |plat| 18 | end") 19 | plat._platform 20 | } 21 | 22 | let (:platform) { 23 | plat = Vanagon::Platform::DSL.new('aix-6.1-ppc') 24 | plat.instance_eval("platform 'aix-6.1-ppc' do |plat| 25 | plat.build_host 'abcd' 26 | end") 27 | plat._platform 28 | } 29 | 30 | describe '#select_target' do 31 | it 'raises an error without a target' do 32 | base = Vanagon::Engine::Hardware.new(platform_without_build_hosts, nil) 33 | expect { base.validate_platform }.to raise_error(Vanagon::Error) 34 | end 35 | 36 | it 'returns a target if one is set' do 37 | base = Vanagon::Engine::Hardware.new(platform, nil) 38 | expect(base).to receive(:node_lock).with(['abcd']).and_return('abcd') 39 | expect(base.select_target).to eq('abcd') 40 | end 41 | end 42 | 43 | describe '#validate_platform' do 44 | it 'raises an error if the platform is missing a required attribute' do 45 | expect{ Vanagon::Engine::Hardware.new(platform_without_build_hosts, nil).validate_platform }.to raise_error(Vanagon::Error) 46 | end 47 | 48 | it 'returns true if the platform has the required attributes' do 49 | expect(Vanagon::Engine::Hardware.new(platform, nil).validate_platform).to be(true) 50 | end 51 | end 52 | 53 | it 'returns "hardware" name' do 54 | expect(Vanagon::Engine::Hardware.new(platform, nil).name).to eq('hardware') 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /spec/lib/vanagon/engine/local_spec.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/engine/local' 2 | require 'vanagon/platform' 3 | 4 | describe 'Vanagon::Engine::Local' do 5 | let (:platform) { 6 | plat = Vanagon::Platform::DSL.new('debian-6-i386') 7 | plat.instance_eval("platform('debian-6-i386') { }") 8 | plat._platform 9 | } 10 | 11 | describe '#validate_platform' do 12 | it 'succeeds' do 13 | expect(Vanagon::Engine::Local.new(platform).validate_platform).to be(true) 14 | end 15 | end 16 | 17 | describe '#dispatch' do 18 | it 'execs successfully' do 19 | engine = Vanagon::Engine::Local.new(platform) 20 | expect(engine.dispatch('true')).to be(true) 21 | end 22 | 23 | it 'returns the result if return_output is true' do 24 | engine = Vanagon::Engine::Local.new(platform) 25 | expect(engine.dispatch('true', true)).to eq('') 26 | end 27 | end 28 | 29 | describe '#retrieve_built_artifacts' do 30 | it 'copies everything if we package' do 31 | engine = Vanagon::Engine::Local.new(platform) 32 | expect(FileUtils).to receive(:mkdir_p).with('output/').and_return true 33 | expect(Dir).to receive(:glob).with('/output/*').and_return(['tmp/foo', 'tmp/bar']) 34 | expect(FileUtils).to receive(:cp_r).with(['tmp/foo', 'tmp/bar'], 'output/') 35 | engine.retrieve_built_artifact([], false) 36 | end 37 | 38 | it "only copies what you tell it to if we don't package" do 39 | engine = Vanagon::Engine::Local.new(platform) 40 | expect(FileUtils).to receive(:mkdir_p).with('output/').and_return true 41 | expect(Dir).to receive(:glob).with('tmp/bar').and_return(['tmp/bar']) 42 | expect(FileUtils).to receive(:cp_r).with(['tmp/bar'], 'output/') 43 | engine.retrieve_built_artifact(['tmp/bar'], true) 44 | end 45 | end 46 | 47 | it 'returns "local" name' do 48 | expect(Vanagon::Engine::Local.new(platform).name).to eq('local') 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /spec/lib/vanagon/extensions/ostruct/json_spec.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/extensions/ostruct/json' 2 | 3 | describe "OpenStruct" do 4 | describe "with JSON mixins" do 5 | let(:test_ostruct) { OpenStruct.new(size: "big", shape: "spherical", name: "rover") } 6 | let(:json_ostruct) { %({"size":"big","shape":"spherical","name":"rover"}) } 7 | 8 | it "responds to #to_json" do 9 | expect(OpenStruct.new.respond_to?(:to_json)).to eq(true) 10 | end 11 | 12 | it "can be converted to a valid JSON object" do 13 | expect(JSON.parse(test_ostruct.to_json)).to eq(JSON.parse(json_ostruct)) 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /spec/lib/vanagon/extensions/set/json_spec.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/extensions/set/json' 2 | 3 | describe "Set" do 4 | describe "with JSON mixins" do 5 | let(:test_set) { Set['a', 'a', 'b', 'c'] } 6 | let(:json_set) { %(["a","b","c"]) } 7 | 8 | it "responds to #to_json" do 9 | expect(Set.new.respond_to?(:to_json)).to eq(true) 10 | end 11 | 12 | it "can be converted to a valid JSON object" do 13 | expect(JSON.parse(test_set.to_json)).to eq(JSON.parse(json_set)) 14 | end 15 | end 16 | end 17 | 18 | -------------------------------------------------------------------------------- /spec/lib/vanagon/extensions/string_spec.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/extensions/string' 2 | 3 | describe "String" do 4 | it "responds to #undent" do 5 | expect(String.new.respond_to?(:undent)).to eq(true) 6 | end 7 | end 8 | 9 | describe "Vanagon::Extensions::String" do 10 | let (:basic_indented_string) { "\s\sa string" } 11 | let (:basic_string) { "a string" } 12 | let (:fancy_indented_string) { "\s\sleading line\n\s\s\s\s\s\strailing line\n\s\s\s\slast line" } 13 | let (:fancy_string) { "leading line\n trailing line\n last line" } 14 | let (:tab_indented_string) { "\t\t\ttab string" } 15 | let (:tab_string) { "tab string" } 16 | 17 | describe "#undent" do 18 | it "trims trivial leading whitespace" do 19 | expect(basic_indented_string.undent).to eq(basic_string) 20 | end 21 | 22 | it "trims more complex whitespace" do 23 | expect(fancy_indented_string.undent).to eq(fancy_string) 24 | end 25 | 26 | it "trims leading tabs" do 27 | expect(tab_indented_string.undent).to eq(tab_string) 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /spec/lib/vanagon/platform/deb_spec.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/platform/deb' 2 | 3 | describe "Vanagon::Platform::DEB" do 4 | let(:platforms) do 5 | [ 6 | { 7 | :name => "ubuntu-10.04-i386", 8 | :os_name => "ubuntu", 9 | :os_version => "10.04", 10 | :architecture => "i386", 11 | :codename => "lucid", 12 | }, 13 | { 14 | :name => "debian-7-amd64", 15 | :os_name => "debian", 16 | :os_version => "7", 17 | :architecture => "amd64", 18 | :codename => "wheezy", 19 | }, 20 | ] 21 | end 22 | end 23 | 24 | 25 | -------------------------------------------------------------------------------- /spec/lib/vanagon/platform/osx_spec.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/platform' 2 | 3 | describe "Vanagon::Platform::OSX" do 4 | let(:block) { 5 | %Q[ platform "osx-10.12-x86_64" do |plat| 6 | end 7 | ] 8 | } 9 | let(:plat) { Vanagon::Platform::DSL.new('osx-10.12-x86_64') } 10 | 11 | before do 12 | plat.instance_eval(block) 13 | end 14 | 15 | describe "osx has a different mktemp" do 16 | it "uses the right mktemp options" do 17 | expect(plat._platform.send(:mktemp)).to eq("mktemp -d -t 'tmp'") 18 | end 19 | end 20 | end 21 | 22 | -------------------------------------------------------------------------------- /spec/lib/vanagon/platform/rpm/aix_spec.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/platform' 2 | 3 | describe "Vanagon::Platform::RPM::AIX" do 4 | let(:block) { 5 | %Q[ platform "aix-5.3-ppc" do |plat| 6 | end 7 | ] 8 | } 9 | let(:plat) { Vanagon::Platform::DSL.new('aix-5.3-ppc') } 10 | 11 | before do 12 | plat.instance_eval(block) 13 | end 14 | 15 | describe '#rpm_defines' do 16 | it "doesn't include dist on aix" do 17 | expect(plat._platform.rpm_defines).to_not include('dist') 18 | end 19 | end 20 | 21 | describe "aix puts commands in weird places" do 22 | it "uses /opt/freeware/bin everwhere" do 23 | ['tar', 'patch', 'install', 'sed'].each do |cmd| 24 | expect(plat._platform.send(cmd.to_sym)).to eq(File.join('/opt/freeware/bin', cmd)) 25 | end 26 | end 27 | end 28 | end 29 | 30 | -------------------------------------------------------------------------------- /spec/lib/vanagon/platform/rpm_spec.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/platform' 2 | 3 | describe 'Vanagon::Platform::RPM' do 4 | platforms = [ 5 | { name: 'el-6-i386' }, 6 | { name: 'fedora-21-x86_64', dist: 'f21' }, 7 | { name: 'cisco-wrlinux-7-x86_64' } 8 | ] 9 | 10 | platforms.each do |platform| 11 | context "defines RPM-based platform attributes for #{platform[:name]}" do 12 | subject { 13 | plat = Vanagon::Platform::DSL.new(platform[:name]) 14 | plat.instance_eval(%(platform("#{platform[:name]}") { |plat| })) 15 | plat._platform.dist = platform[:dist] 16 | plat._platform 17 | } 18 | 19 | let(:derived_dist) { subject.os_name.tr('-', '_') + subject.os_version } 20 | let(:dist) { platform[:dist] || derived_dist } 21 | let(:defined_dist) { "--define 'dist .#{dist}'" } 22 | 23 | describe '#rpm_defines' do 24 | it "includes the expected 'dist' defines" do 25 | expect(subject.rpm_defines).to include(defined_dist) 26 | end 27 | end 28 | 29 | describe '#source_output_dir' do 30 | it "includes 'SRPMS'" do 31 | expect(subject.source_output_dir).to include('SRPMS') 32 | end 33 | end 34 | 35 | describe "#dist" do 36 | it "uses explicit values when available" do 37 | expect(subject.dist).to eq(derived_dist) unless platform[:dist] 38 | expect(subject.dist).to eq(dist) 39 | end 40 | end 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /spec/lib/vanagon/platform/solaris_10_spec.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/platform' 2 | 3 | describe "Vanagon::Platform::Solaris10" do 4 | let(:block) { 5 | %Q[ platform "solaris-10-i386" do |plat| 6 | end 7 | ] 8 | } 9 | let(:plat) { Vanagon::Platform::DSL.new('solaris-10-i386') } 10 | 11 | before do 12 | plat.instance_eval(block) 13 | end 14 | 15 | describe "solaris10 has weird paths for gnu commands" do 16 | it "has some in /opt/csw/bin" do 17 | ['make', 'sed'].each do |cmd| 18 | expect(plat._platform.send(cmd.to_sym)).to eq(File.join('/opt/csw/bin', "g#{cmd}")) 19 | end 20 | end 21 | it "uses /usr/sfw/bin/gtar" do 22 | expect(plat._platform.send(:tar)).to eq('/usr/sfw/bin/gtar') 23 | end 24 | it "uses /usr/bin/gpatch" do 25 | expect(plat._platform.send(:patch)).to eq('/usr/bin/gpatch') 26 | end 27 | end 28 | end 29 | 30 | -------------------------------------------------------------------------------- /spec/lib/vanagon/platform/solaris_11_spec.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/platform/solaris_11' 2 | 3 | describe "Vanagon::Platform::Solaris_11" do 4 | let(:platform) do 5 | { 6 | :name => 'solaris-11-i386', 7 | :block => %Q[platform "solaris-11-i386" do |plat| end] 8 | } 9 | end 10 | 11 | let(:versions) do 12 | [ 13 | # Leading and trailing - stripped 14 | { :original => "-1.2.3-", :final => "1.2.3" }, 15 | 16 | # Non-numeric stripped 17 | { :original => "-1.2bcd.3aaz-", :final => "1.2.3" }, 18 | 19 | # Leading, non-singular zeroes stripped 20 | { :original => "1.0.2.00123", :final => "1.0.2.123" }, 21 | { :original => "1.0000.2.00123", :final => "1.0.2.123" }, 22 | ] 23 | end 24 | 25 | describe '#ips_version' do 26 | it 'strips invalid characters from the version' do 27 | versions.each do |ver| 28 | plat = Vanagon::Platform::DSL.new(platform[:name]) 29 | plat.instance_eval(platform[:block]) 30 | expect(plat._platform.ips_version(ver[:original], '1')).to eq("#{ver[:final]},5.11-1") 31 | end 32 | end 33 | 34 | it 'handles the release field correctly' do 35 | 1.upto(3) do |i| 36 | versions.each do |ver| 37 | plat = Vanagon::Platform::DSL.new(platform[:name]) 38 | plat.instance_eval(platform[:block]) 39 | expect(plat._platform.ips_version(ver[:original], i)).to eq("#{ver[:final]},5.11-#{i}") 40 | end 41 | end 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /spec/lib/vanagon/utilities/shell_utilities_spec.rb: -------------------------------------------------------------------------------- 1 | require 'vanagon/utilities/shell_utilities' 2 | 3 | describe Vanagon::Utilities::ShellUtilities do 4 | describe "#cmdjoin" do 5 | it "returns a single value as-is" do 6 | expect(described_class.cmdjoin(["make test"], " !! ")).to eq "make test" 7 | end 8 | 9 | it "turns an array with a single value into the wrapped value" do 10 | expect(described_class.cmdjoin([["make test"]], " !! ")).to eq "make test" 11 | end 12 | 13 | it "joins multiple commands with the separator string" do 14 | expect(described_class.cmdjoin(["cd build", "cmake ..", "make"], " !! ")).to eq "cd build !! cmake .. !! make" 15 | end 16 | 17 | it "joins single strings and arrays of strings" do 18 | expect(described_class.cmdjoin([ 19 | "cd build", 20 | ["make", "make test"] 21 | ], " !! ")).to eq "cd build !! make !! make test" 22 | end 23 | end 24 | 25 | it "#andand joins commands with &&" do 26 | expect(described_class.andand("foo", ["bar", "baz"])).to eq "foo && bar && baz" 27 | end 28 | 29 | it "#andand_multiline joins commands with && and an escaped newline" do 30 | expect(described_class.andand_multiline("foo", ["bar", "baz"])).to eq "foo && \\\nbar && \\\nbaz" 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # Coverage configuration should come ahead of everything else. 2 | # This will ensure that code paths are followed appropriately. 3 | if ENV["COVERAGE"] 4 | require 'simplecov' 5 | SimpleCov.start do 6 | add_filter '.bundle' 7 | add_filter 'spec' 8 | add_filter 'vendor' 9 | 10 | # Define a minimum coverage score, and fail if it's not met. 11 | # This should probably be a Float, not an Integer but as 12 | # long as it's not a String it's probably fine. 13 | # 14 | # The coverage score on 2017-02-07 for commit 770b67db was 71.85 15 | # - Ryan McKern, 2017-02-07 16 | minimum_coverage ENV['MINIMUM_SCORE'] || 70.00 17 | end 18 | end 19 | 20 | require 'tmpdir' 21 | require 'vanagon' 22 | require 'webmock/rspec' 23 | 24 | RSpec.configure do |c| 25 | c.before do 26 | allow_any_instance_of(Vanagon::Component::Source::Git).to receive(:puts) 27 | allow_any_instance_of(Vanagon::Component::Source::Http).to receive(:puts) 28 | allow_any_instance_of(Vanagon::Component::Source::Local).to receive(:puts) 29 | 30 | class Vanagon 31 | module Utilities 32 | def puts(*args) 33 | end 34 | end 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /vanagon.gemspec: -------------------------------------------------------------------------------- 1 | require 'time' 2 | 3 | Gem::Specification.new do |gem| 4 | gem.name = 'vanagon' 5 | gem.version = %x(git describe --tags).tr('-', '.').chomp 6 | 7 | gem.summary = 'Multiplatform build, sign, and ship for Puppet projects' 8 | gem.description = <<-DESCRIPTION 9 | Vanagon takes a set of project, component, and platform configuration files, to perform 10 | multiplatform builds that are packaged into rpms, debs, dmgs, etc. 11 | It has support for calls into Puppet's packaging gem to provide for package signing and 12 | shipping within the Puppet infrastructure. 13 | DESCRIPTION 14 | gem.license = 'Apache-2.0' 15 | 16 | gem.authors = ['Puppet By Perforce'] 17 | gem.email = 'release@puppet.com' 18 | gem.homepage = 'http://github.com/puppetlabs/vanagon' 19 | gem.required_ruby_version = '>=2.3', '<4' 20 | 21 | gem.add_runtime_dependency('docopt') 22 | # Handle git repos responsibly 23 | # - MIT licensed: https://rubygems.org/gems/git 24 | gem.add_runtime_dependency('git', '~> 1.13.0') 25 | # Parse scp-style triplets like URIs; used for Git source handling. 26 | # - MIT licensed: https://rubygems.org/gems/build-uri 27 | gem.add_runtime_dependency('build-uri', '~> 1.0') 28 | # Handle locking hardware resources 29 | # - ASL v2 licensed: https://rubygems.org/gems/lock_manager 30 | gem.add_runtime_dependency('lock_manager', '>= 0') 31 | # Utilities for `ship` and `repo` commands 32 | # - ASL v2 licensed: https://rubygems.org/gems/packaging 33 | gem.add_runtime_dependency('packaging') 34 | gem.add_runtime_dependency('psych', '>= 4.0') 35 | 36 | gem.require_path = 'lib' 37 | gem.bindir = 'bin' 38 | gem.executables = %w[vanagon build inspect ship render repo sign 39 | build_host_info build_requirements] 40 | 41 | # Ensure the gem is built out of versioned files 42 | gem.files = Dir['{bin,extras,lib,spec,resources}/**/*', 'README*', 'LICENSE*'] & 43 | %x(git ls-files -z).split("\0") 44 | end 45 | --------------------------------------------------------------------------------