Merge remote-tracking branch 'upstream/master' into stable

Prepare for 3.5.0-rc1

* upstream/master: (800 commits)
  (PUP-1085) Add and fix pacman provider tests
  (PUP-1905) Split modulepath when supplied as an override from CLI
  (PUP-1897) Improve test of EPP trim, and expr after params
  (PUP-1897) Fix failing lexer2 test, and update with additional tests
  (PUP-1897) Change epp lexer/grammar to only accept single rendered expr
  (PUP-979) Fix unparenthesized calls with hash to not give strange error
  (PUP-1897) Allow EPP render expression to render a block
  (maint) Remove dead-code check if ImportExpression is r-value
  (maint) Remove dead code checking non existing ImportExpression
  (PUP-1898) Fix reference to ArgumentException
  (PUP-1898) Fix broken exception raising when inline_epp gets non string
  (PUP-1895) Change <%( )%> to <%| |%> for EPP parameters
  (maint) Fix parallel:spec rake task when dependencies are not present.
  (Maint) Remove some duplication in tests
  (PUP-1885) Stringify ignores for file serving
  (PUP-1563) Don't recurse when dependencies are empty
  (PUP-1563) resolve_install_conflicts excessively recurses
  (maint) Add rake task for parallelizing specs.
  (PUP-30) Fix problem with changed behavior in StringScanner.scan_until
  (PUP-30) Add tests of inline_epp function
  ...
This commit is contained in:
Andrew Parker 2014-03-11 13:37:11 -07:00
Родитель f7ea50593d ae1f2933a4
Коммит a05d9b4e6b
974 изменённых файлов: 33294 добавлений и 14182 удалений

Просмотреть файл

@ -42,14 +42,14 @@ Gem::Specification.new do |s|
s.specification_version = 3
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q<facter>, ["> 1.5", "< 3"])
s.add_runtime_dependency(%q<facter>, [">= 1.7", "< 3"])
s.add_runtime_dependency(%q<hiera>, ["~> 1.0"])
else
s.add_dependency(%q<facter>, ["> 1.5", "< 3"])
s.add_dependency(%q<facter>, [">= 1.7", "< 3"])
s.add_dependency(%q<hiera>, ["~> 1.0"])
end
else
s.add_dependency(%q<facter>, ["> 1.5", "< 3"])
s.add_dependency(%q<facter>, [">= 1.7", "< 3"])
s.add_dependency(%q<hiera>, ["~> 1.0"])
end
end

2
.gitignore поставляемый
Просмотреть файл

@ -20,3 +20,5 @@ Gemfile.local
puppet-acceptance/
/.project
.idea/
.ruby-version
.ruby-gemset

Просмотреть файл

@ -1,9 +1,10 @@
language: ruby
bundler_args: --without development
script: "bundle exec rake spec"
script: "bundle exec rake \"parallel:spec[1]\""
notifications:
email: false
rvm:
- 2.1.0
- 2.0.0
- 1.9.3
- 1.8.7

Просмотреть файл

@ -9,7 +9,7 @@ top of things.
## Getting Started
* Make sure you have a [Redmine account](http://projects.puppetlabs.com)
* Make sure you have a [Jira account](http://tickets.puppetlabs.com)
* Make sure you have a [GitHub account](https://github.com/signup/free)
* Submit a ticket for your issue, assuming one does not already exist.
* Clearly describe the issue including steps to reproduce when it is a bug.
@ -31,7 +31,7 @@ top of things.
* Make sure your commit messages are in the proper format.
````
(#99999) Make the example in CONTRIBUTING imperative and concrete
(PUP-1234) Make the example in CONTRIBUTING imperative and concrete
Without this patch applied the example commit message in the CONTRIBUTING
document is not a concrete example. This is a problem because the
@ -52,7 +52,7 @@ top of things.
### Documentation
For changes of a trivial nature to comments and documentation, it is not
always necessary to create a new ticket in Redmine. In this case, it is
always necessary to create a new ticket in Jira. In this case, it is
appropriate to start the first line of a commit with '(doc)' instead of
a ticket number.
@ -74,13 +74,13 @@ a ticket number.
* Sign the [Contributor License Agreement](http://links.puppetlabs.com/cla).
* Push your changes to a topic branch in your fork of the repository.
* Submit a pull request to the repository in the puppetlabs organization.
* Update your Redmine ticket to mark that you have submitted code and are ready for it to be reviewed.
* Include a link to the pull request in the ticket
* Update your Jira ticket to mark that you have submitted code and are ready for it to be reviewed (Status: Ready for Merge).
* Include a link to the pull request in the ticket.
# Additional Resources
* [More information on contributing](http://links.puppetlabs.com/contribute-to-puppet)
* [Bug tracker (Redmine)](http://projects.puppetlabs.com)
* [Bug tracker (Jira)](http://tickets.puppetlabs.com)
* [Contributor License Agreement](http://links.puppetlabs.com/cla)
* [General GitHub documentation](http://help.github.com/)
* [GitHub pull request documentation](http://help.github.com/send-pull-requests/)

36
Gemfile
Просмотреть файл

@ -44,12 +44,20 @@ group(:development, :test) do
gem "multi_json", "1.7.7", :require => false
gem "json-schema", "2.1.1", :require => false
end
end
group(:development) do
case RUBY_VERSION
when /^1.8/
gem 'ruby-prof', "~> 0.13.1", :require => false
else
gem 'ruby-prof', :require => false
end
end
group(:extra) do
gem "rack", "~> 1.4", :require => false
gem "activerecord", '~> 3.0.7', :require => false
gem "activerecord", '~> 3.2', :require => false
gem "couchrest", '~> 1.0', :require => false
gem "net-ssh", '~> 2.1', :require => false
gem "puppetlabs_spec_helper", :require => false
@ -59,20 +67,18 @@ group(:extra) do
gem "msgpack", :require => false
end
platforms :mswin, :mingw do
gem "ffi", "1.9.0", :require => false
gem "sys-admin", "1.5.6", :require => false
gem "win32-api", "1.4.8", :require => false
gem "win32-dir", "0.4.3", :require => false
gem "win32-eventlog", "0.5.3", :require => false
gem "win32-process", "0.6.5", :require => false
gem "win32-security", "0.1.4", :require => false
gem "win32-service", "0.7.2", :require => false
gem "win32-taskscheduler", "0.2.2", :require => false
gem "win32console", "1.3.2", :require => false
gem "windows-api", "0.4.2", :require => false
gem "windows-pr", "1.2.2", :require => false
gem "minitar", "0.5.4", :require => false
require 'yaml'
data = YAML.load_file(File.join(File.dirname(__FILE__), 'ext', 'project_data.yaml'))
bundle_platforms = data['bundle_platforms']
data['gem_platform_dependencies'].each_pair do |gem_platform, info|
if bundle_deps = info['gem_runtime_dependencies']
bundle_platform = bundle_platforms[gem_platform] or raise "Missing bundle_platform"
platform(bundle_platform.intern) do
bundle_deps.each_pair do |name, version|
gem(name, version, :require => false)
end
end
end
end
if File.exists? "#{__FILE__}.local"

Просмотреть файл

@ -1,6 +1,6 @@
Puppet - Automating Configuration Management.
Copyright (C) 2005-2012 Puppet Labs Inc
Copyright (C) 2005-2014 Puppet Labs Inc
Puppet Labs can be contacted at: info@puppetlabs.com

Просмотреть файл

@ -13,6 +13,10 @@ Documentation
Documentation for Puppet and related projects can be found online at the
[Puppet Docs site](http://docs.puppetlabs.com).
HTTP API
--------
[HTTP API Index](api/docs/http_api_index.md)
Installation
------------
@ -26,28 +30,46 @@ To install an open source release of Puppet,
If you need to run Puppet from source as a tester or developer,
[see the running from source guide on the docs site.](http://docs.puppetlabs.com/guides/from_source.html)
Contributions
Developing and Contributing
------
Please see our [Contribution
Documents](https://github.com/puppetlabs/puppet/blob/master/CONTRIBUTING.md)
and our [Developer
Documentation](https://github.com/puppetlabs/puppet/blob/master/README_DEVELOPER.md).
We'd love to get contributions from you! For a quick guide to getting your
system setup for developing take a look at our [Quickstart
Guide](docs/quickstart.md). Once you are up and running, take a look at the
[Contribution Documents](CONTRIBUTING.md) to see how to get your changes merged
in.
For more complete docs on developing with puppet you can take a look at the
rest of the [developer documents](docs/index.md).
License
-------
See LICENSE file.
See [LICENSE](LICENSE) file.
Support
-------
Please log tickets and issues at our [Projects
site](http://projects.puppetlabs.com). A [mailing
Please log tickets and issues at our [JIRA tracker](http://tickets.puppetlabs.com). A [mailing
list](https://groups.google.com/forum/?fromgroups#!forum/puppet-users) is
available for asking questions and getting help from others. In addition there
is an active #puppet channel on Freenode.
HTTP API
--------
{file:api/docs/http_api_index.md HTTP API Index}
We use semantic version numbers for our releases, and recommend that users stay
as up-to-date as possible by upgrading to patch releases and minor releases as
they become available.
Bugfixes and ongoing development will occur in minor releases for the current
major version. Security fixes will be backported to a previous major version on
a best-effort basis, until the previous major version is no longer maintained.
For example: If a security vulnerability is discovered in Puppet 4.1.1, we
would fix it in the 4 series, most likely as 4.1.2. Maintainers would then make
a best effort to backport that fix onto the latest Puppet 3 release.
Long-term support, including security patches and bug fixes, is available for
commercial customers. Please see the following page for more details:
[Puppet Enterprise Support Lifecycle](http://puppetlabs.com/misc/puppet-enterprise-lifecycle)

Просмотреть файл

@ -1,809 +0,0 @@
# Developer README #
This file is intended to provide a place for developers and contributors to
document what other developers need to know about changes made to Puppet.
# Internal Structures
## Two Types of Catalog
When working on subsystems of Puppet that deal with the catalog it is important
to be aware of the two different types of Catalog. Developers will often find
this difference while working on the static compiler and types and providers.
The two different types of catalog becomes relevant when writing spec tests
because we frequently need to wire up a fake catalog so that we can exercise
types, providers, or termini that filter the catalog.
The two different types of catalogs are so-called "resource" catalogs and "RAL"
(resource abstraction layer) catalogs. At a high level, the resource catalog
is the in-memory object we serialize and transfer around the network. The
compiler terminus is expected to produce a resource catalog. The agent takes a
resource catalog and converts it into a RAL catalog. The RAL catalog is what
is used to apply the configuration model to the system.
Resource dependency information is most easily obtained from a RAL catalog by
walking the graph instance produced by the `relationship_graph` method.
### Resource Catalog
If you're writing spec tests for something that deals with a catalog "server
side," a new catalog terminus for example, then you'll be dealing with a
resource catalog. You can produce a resource catalog suitable for spec tests
using something like this:
let(:catalog) do
catalog = Puppet::Resource::Catalog.new("node-name-val") # NOT certname!
rsrc = Puppet::Resource.new("file", "sshd_config",
:parameters => {
:ensure => 'file',
:source => 'puppet:///modules/filetest/sshd_config',
}
)
rsrc.file = 'site.pp'
rsrc.line = 21
catalog.add_resource(rsrc)
end
The resources in this catalog may be accessed using `catalog.resources`.
Resource dependencies are not easily walked using a resource catalog however.
To walk the dependency tree convert the catalog to a RAL catalog as described
in
### RAL Catalog
The resource catalog may be converted to a RAL catalog using `catalog.to_ral`.
The RAL catalog contains `Puppet::Type` instances instead of `Puppet::Resource`
instances as is the case with the resource catalog.
One very useful feature of the RAL catalog are the methods to work with
resource relationships. For example:
irb> catalog = catalog.to_ral
irb> graph = catalog.relationship_graph
irb> pp graph.edges
[{ Notify[alpha] => File[/tmp/file_20.txt] },
{ Notify[alpha] => File[/tmp/file_21.txt] },
{ Notify[alpha] => File[/tmp/file_22.txt] },
{ Notify[alpha] => File[/tmp/file_23.txt] },
{ Notify[alpha] => File[/tmp/file_24.txt] },
{ Notify[alpha] => File[/tmp/file_25.txt] },
{ Notify[alpha] => File[/tmp/file_26.txt] },
{ Notify[alpha] => File[/tmp/file_27.txt] },
{ Notify[alpha] => File[/tmp/file_28.txt] },
{ Notify[alpha] => File[/tmp/file_29.txt] },
{ File[/tmp/file_20.txt] => Notify[omega] },
{ File[/tmp/file_21.txt] => Notify[omega] },
{ File[/tmp/file_22.txt] => Notify[omega] },
{ File[/tmp/file_23.txt] => Notify[omega] },
{ File[/tmp/file_24.txt] => Notify[omega] },
{ File[/tmp/file_25.txt] => Notify[omega] },
{ File[/tmp/file_26.txt] => Notify[omega] },
{ File[/tmp/file_27.txt] => Notify[omega] },
{ File[/tmp/file_28.txt] => Notify[omega] },
{ File[/tmp/file_29.txt] => Notify[omega] }]
If the `relationship_graph` method is throwing exceptions at you, there's a
good chance the catalog is not a RAL catalog.
## Settings Catalog ##
Be aware that Puppet creates a mini catalog and applies this catalog locally to
manage file resource from the settings. This behavior made it difficult and
time consuming to track down a race condition in
[2888](http://projects.puppetlabs.com/issues/2888).
Even more surprising, the `File[puppetdlockfile]` resource is only added to the
settings catalog if the file exists on disk. This caused the race condition as
it will exist when a separate process holds the lock while applying the
catalog.
It may be sufficient to simply be aware of the settings catalog and the
potential for race conditions it presents. An effective way to be reasonably
sure and track down the problem is to wrap the File.open method like so:
# We're wrapping ourselves around the File.open method.
# As described at: http://goo.gl/lDsv6
class File
WHITELIST = [ /pidlock.rb:39/ ]
class << self
alias xxx_orig_open open
end
def self.open(name, *rest, &block)
# Check the whitelist for any "good" File.open calls against the #
puppetdlock file
white_listed = caller(0).find do |line|
JJM_WHITELIST.find { |re| re.match(line) }
end
# If you drop into IRB here, take a look at your caller, it might be
# the ghost in the machine you're looking for.
binding.pry if name =~ /puppetdlock/ and not white_listed
xxx_orig_open(name, *rest, &block)
end
end
The settings catalog is populated by the `Puppet::Util::Settings#to\_catalog`
method.
# Ruby Dependencies #
To install the dependencies run:
$ bundle install --path .bundle/gems/
Once this is done, you can interact with puppet through bundler using `bundle
exec <command>` which will ensure that `<command>` is executed in the context
of puppet's dependencies.
For example to run the specs:
$ bundle exec rake spec
To run puppet itself (for a resource lookup say):
$ bundle exec puppet resource host localhost
which should return something like:
host { 'localhost':
ensure => 'present',
ip => '127.0.0.1',
target => '/etc/hosts',
}
# Running Tests #
Puppet Labs projects use a common convention of using Rake to run unit tests.
The tests can be run with the following rake task:
bundle exec rake spec
This allows the Rakefile to set up the environment beforehand if needed. This
method is how the unit tests are run in [Jenkins](https://jenkins.puppetlabs.com).
Under the hood Puppet's tests use `rspec`. To run all of them, you can directly
use 'rspec':
bundle exec rspec
To run a single file's worth of tests (much faster!), give the filename, and use
the nested format to see the descriptions:
bundle exec rspec spec/unit/ssl/host_spec.rb --format nested
## Testing dependency version requirements
Puppet is only compatible with certain versions of RSpec and Mocha. If you are
not using Bundler to install the required test libraries you must ensure that
you are using the right library versions. Using unsupported versions of Mocha
and RSpec will probably display many spurious failures. The supported versions
of RSpec and Mocha can be found in the project Gemfile.
# A brief introduction to testing in Puppet
Puppet relies heavily on automated testing to ensure that Puppet behaves as
expected and that new features don't interfere with existing behavior. There are
three primary sets of tests that Puppet uses: _unit tests_, _integration tests_,
and _acceptance tests_.
- - -
Unit tests are used to test the individual components of Puppet to ensure that
they function as expected in isolation. Unit tests are designed to hide the
actual system implementations and provide canned information so that only the
intended behavior is tested, rather than the targeted code and everything else
connected to it. Unit tests should never affect the state of the system that's
running the test.
- - -
Integration tests serve to test different units of code together to ensure that
they interact correctly. While individual methods might perform correctly, when
used with the rest of the system they might fail, so integration tests are a
higher level version of unit tests that serve to check the behavior of
individual subsystems.
All of the unit and integration tests for Puppet are kept in the spec/ directory.
- - -
Acceptance tests are used to test high level behaviors of Puppet that deal with
a number of concerns and aren't easily tested with normal unit tests. Acceptance
tests function by changing system state and checking the system after
the fact to make sure that the intended behavior occurred. Because of this
acceptance tests can be destructive, so the systems being tested should be
throwaway systems.
All of the acceptance tests for Puppet are kept in the acceptance/tests/
directory.
## Puppet Continuous integration
* Travis-ci (unit tests only): https://travis-ci.org/puppetlabs/puppet/
* Jenkins (unit and acceptance tests): https://jenkins.puppetlabs.com/view/Puppet%20FOSS/
## RSpec
Puppet uses RSpec to perform unit and integration tests. RSpec handles a number
of concerns to make testing easier:
* Executing examples and ensuring the actual behavior matches the expected behavior (examples)
* Grouping tests (describe and contexts)
* Setting up test environments and cleaning up afterwards (before and after blocks)
* Isolating tests (mocks and stubs)
#### Examples and expectations
At the most basic level, RSpec provides a framework for executing tests (which
are called examples) and ensuring that the actual behavior matches the expected
behavior (which are done with expectations)
```ruby
# This is an example; it sets the test name and defines the test to run
specify "one equals one" do
# 'should' is an expectation; it adds a check to make sure that the left argument
# matches the right argument
1.should == 1
end
# Examples can be declared with either 'it' or 'specify'
it "one doesn't equal two" do
1.should_not == 2
end
```
Good examples generally do as little setup as possible and only test one or two
things; it makes tests easier to understand and easier to debug.
More complete documentation on expectations is available at https://www.relishapp.com/rspec/rspec-expectations/docs
### Example groups
Example groups are fairly self explanatory; they group similar examples into a
set.
```ruby
describe "the number one" do
it "is larger than zero" do
1.should be > 0
end
it "is an odd number" do
1.odd?.should be true
end
it "is not nil" do
1.should_not be_nil
end
end
```
Example groups have a number of uses that we'll get into later, but one of the
simplest demonstrations of what they do is how they help to format
documentation:
```
rspec ex.rb --format documentation
the number one
is larger than zero
is an odd number
is not nil
Finished in 0.00516 seconds
3 examples, 0 failures
```
### Setting up and tearing down tests
Examples may require some setup before they can run, and might need to clean up
afterwards. `before` and `after` blocks can be used before this, and can be
used inside of example groups to limit how many examples they affect.
```ruby
describe "something that could warn" do
before :each do
# Disable warnings for this test
$VERBOSE = nil
end
after do
# Enable warnings afterwards
$VERBOSE = true
end
it "doesn't generate a warning" do
MY_CONSTANT = 1
# reassigning a normally prints out 'warning: already initialized constant FOO'
MY_CONSTANT = 2
end
end
```
### Setting up helper data
Some examples may require setting up data before hand and making it available to
tests. RSpec provides helper methods with the `let` method call that can be used
inside of tests.
```ruby
describe "a helper object" do
# This creates an array with three elements that we can retrieve in tests. A
# new copy will be made for each test.
let(:my_helper) do
['foo', 'bar', 'baz']
end
it "should be an array" do
my_helper.should be_a_kind_of Array
end
it "should have three elements" do
my_helper.should have(3).items
end
end
```
Like `before` blocks, helper objects like this are used to avoid doing a lot of
setup in individual examples and share setup between similar tests.
### Isolating tests with stubs
RSpec allows you to provide fake data during testing to make sure that
individual tests are only running the code being tested. You can stub out entire
objects, or just stub out individual methods on an object. When a method is
stubbed the method itself will never be called.
While RSpec comes with its own stubbing framework, Puppet uses the Mocha
framework.
A brief usage guide for Mocha is available at http://gofreerange.com/mocha/docs/#Usage,
and an overview of Mocha expectations is available at http://gofreerange.com/mocha/docs/Mocha/Expectation.html
```ruby
describe "stubbing a method on an object" do
let(:my_helper) do
['foo', 'bar', 'baz']
end
it 'should have three items before being stubbed' do
my_helper.size.should == 3
end
describe 'when stubbing the size' do
before do
my_helper.stubs(:size).returns 10
end
it 'should have the stubbed value for size' do
my_helper.size.should == 10
end
end
end
```
Entire objects can be stubbed as well.
```ruby
describe "stubbing an object" do
let(:my_helper) do
stub(:not_an_array, :size => 10)
end
it 'should have the stubbed size'
my_helper.size.should == 10
end
end
```
### Adding expectations with mocks
It's possible to combine the concepts of stubbing and expectations so that a
method has to be called for the test to pass (like an expectation), and can
return a fixed value (like a stub).
```ruby
describe "mocking a method on an object" do
let(:my_helper) do
['foo', 'bar', 'baz']
end
describe "when mocking the size" do
before do
my_helper.expects(:size).returns 10
end
it "adds an expectation that a method was called" do
my_helper.size
end
end
end
```
Like stubs, entire objects can be mocked.
```ruby
describe "mocking an object" do
let(:my_helper) do
mock(:not_an_array)
end
before do
not_an_array.expects(:size).returns 10
end
it "adds an expectation that the method was called" do
not_an_array.size
end
end
```
### Writing tests without side effects
When properly written each test should be able to run in isolation, and tests
should be able to be run in any order. This makes tests more reliable and allows
a single test to be run if only that test is failing, instead of running all
17000+ tests each time something is changed. However, there are a number of ways
that can make tests fail when run in isolation or out of order.
#### Using instance variables
Puppet has a number of older tests that use `before` blocks and instance
variables to set up fixture data, instead of `let` blocks. These can retain
state between tests, which can lead to test failures when tests are run out of
order.
```ruby
# test.rb
RSpec.configure do |c|
c.mock_framework = :mocha
end
describe "fixture data" do
describe "using instance variables" do
# BAD
before :all do
# This fixture will be created only once and will retain the `foo` stub
# between tests.
@fixture = stub 'test data'
end
it "can be stubbed" do
@fixture.stubs(:foo).returns :bar
@fixture.foo.should == :bar
end
it "should not keep state between tests" do
# The foo stub was added in the previous test and shouldn't be present
# in this test.
expect { @fixture.foo }.to raise_error
end
end
describe "using `let` blocks" do
# GOOD
# This will be recreated between tests so that state isn't retained.
let(:fixture) { stub 'test data' }
it "can be stubbed" do
fixture.stubs(:foo).returns :bar
fixture.foo.should == :bar
end
it "should not keep state between tests" do
# since let blocks are regenerated between tests, the foo stub added in
# the previous test will not be present here.
expect { fixture.foo }.to raise_error
end
end
end
```
```
bundle exec rspec test.rb -fd
fixture data
using instance variables
can be stubbed
should not keep state between tests (FAILED - 1)
using `let` blocks
can be stubbed
should not keep state between tests
Failures:
1) fixture data using instance variables should not keep state between tests
Failure/Error: expect { @fixture.foo }.to raise_error
expected Exception but nothing was raised
# ./test.rb:17:in `block (3 levels) in <top (required)>'
Finished in 0.00248 seconds
4 examples, 1 failure
Failed examples:
rspec ./test.rb:16 # fixture data using instance variables should not keep state between tests
```
### RSpec references
* RSpec core docs: https://www.relishapp.com/rspec/rspec-core/docs
* RSpec guidelines with Ruby: http://betterspecs.org/
### Puppet-acceptance
[puppet-acceptance]: https://github.com/puppetlabs/puppet-acceptance
[test::unit]: http://test-unit.rubyforge.org/
Puppet has a custom acceptance testing framework called
[puppet-acceptance][puppet-acceptance] for running acceptance tests.
Puppet-acceptance runs the tests by configuring one or more VMs, copying the
test cases onto the VMs, performing the tests and collecting the results, and
ensuring that the results match the intended behavior. It uses
[test::unit][test::unit] to perform the actual assertions.
# UTF-8 Handling #
As Ruby 1.9 becomes more commonly used with Puppet, developers should be aware
of major changes to the way Strings and Regexp objects are handled.
Specifically, every instance of these two classes will have an encoding
attribute determined in a number of ways.
* If the source file has an encoding specified in the magic comment at the
top, the instance will take on that encoding.
* Otherwise, the encoding will be determined by the LC\_LANG or LANG
environment variables.
* Otherwise, the encoding will default to ASCII-8BIT
## References ##
Excellent information about the differences between encodings in Ruby 1.8 and
Ruby 1.9 is published in this blog series:
[Understanding M17n](http://links.puppetlabs.com/understanding_m17n)
## Encodings of Regexp and String instances ##
In general, please be aware that Ruby 1.9 regular expressions need to be
compatible with the encoding of a string being used to match them. If they are
not compatible you can expect to receive and error such as:
Encoding::CompatibilityError: incompatible encoding regexp match (ASCII-8BIT
regexp with UTF-8 string)
In addition, some escape sequences were valid in Ruby 1.8 are no longer valid
in 1.9 if the regular expression is not marked as an ASCII-8BIT object. You
may expect errors like this in this situation:
SyntaxError: (irb):7: invalid multibyte escape: /\xFF/
This error is particularly common when serializing a string to other
representations like JSON or YAML. To resolve the problem you can explicitly
mark the regular expression as ASCII-8BIT using the /n flag:
"a" =~ /\342\230\203/n
Finally, any time you're thinking of a string as an array of bytes rather than
an array of characters, common when escaping a string, you should work with
everything in ASCII-8BIT. Changing the encoding will not change the data
itself and allow the Regexp and the String to deal with bytes rather than
characters.
Puppet provides a monkey patch to String which returns an encoding suitable for
byte manipulations:
# Example of how to escape non ASCII printable characters for YAML.
>> snowman = "☃"
>> snowman.to_ascii8bit.gsub(/([\x80-\xFF])/n) { |x| "\\x#{x.unpack("C")[0].to_s(16)} }
=> "\\xe2\\x98\\x83"
If the Regexp is not marked as ASCII-8BIT using /n, then you can expect the
SyntaxError, invalid multibyte escape as mentioned above.
# Windows #
If you'd like to run Puppet from source on Windows platforms, the
include `ext/envpuppet.bat` will help.
To quickly run Puppet from source, assuming you already have Ruby installed
from [rubyinstaller.org](http://rubyinstaller.org).
C:\> cd C:\work\puppet
C:\work\puppet> set PATH=%PATH%;C:\work\puppet\ext
C:\work\puppet> envpuppet bundle install
C:\work\puppet> envpuppet puppet --version
2.7.9
When writing a test that cannot possibly run on Windows, e.g. there is
no mount type on windows, do the following:
describe Puppet::MyClass, :unless => Puppet.features.microsoft_windows? do
..
end
If the test doesn't currently pass on Windows, e.g. due to on going porting, then use an rspec conditional pending block:
pending("porting to Windows", :if => Puppet.features.microsoft_windows?) do
<example1>
end
pending("porting to Windows", :if => Puppet.features.microsoft_windows?) do
<example2>
end
Then run the test as:
C:\work\puppet> envpuppet bundle exec rspec spec
## Common Issues ##
* Don't assume file paths start with '/', as that is not a valid path on
Windows. Use Puppet::Util.absolute\_path? to validate that a path is fully
qualified.
* Use File.expand\_path('/tmp') in tests to generate a fully qualified path
that is valid on POSIX and Windows. In the latter case, the current working
directory will be used to expand the path.
* Always use binary mode when performing file I/O, unless you explicitly want
Ruby to translate between unix and dos line endings. For example, opening an
executable file in text mode will almost certainly corrupt the resulting
stream, as will occur when using:
IO.open(path, 'r') { |f| ... }
IO.read(path)
If in doubt, specify binary mode explicitly:
IO.open(path, 'rb')
* Don't assume file paths are separated by ':'. Use `File::PATH_SEPARATOR`
instead, which is ':' on POSIX and ';' on Windows.
* On Windows, `File::SEPARATOR` is '/', and `File::ALT_SEPARATOR` is '\'. On
POSIX systems, `File::ALT_SEPARATOR` is nil. In general, use '/' as the
separator as most Windows APIs, e.g. CreateFile, accept both types of
separators.
* Don't use waitpid/waitpid2 if you need the child process' exit code,
as the child process may exit before it has a chance to open the
child's HANDLE and retrieve its exit code. Use Puppet::Util.execute.
* Don't assume 'C' drive. Use environment variables to look these up:
"#{ENV['windir']}/system32/netsh.exe"
# Configuration Directory #
In Puppet 3.x we've simplified the behavior of selecting a configuration file
to load. The intended behavior of reading `puppet.conf` is:
1. Use the explicit configuration provided by --confdir or --config if present
2. If running as root (`Puppet.features.root?`) then use the system
`puppet.conf`
3. Otherwise, use `~/.puppet/puppet.conf`.
When Puppet master is started from Rack, Puppet 3.x will read from
~/.puppet/puppet.conf by default. This is intended behavior. Rack
configurations should start Puppet master with an explicit configuration
directory using `ARGV << "--confdir" << "/etc/puppet"`. Please see the
`ext/rack/config.ru` file for an up-to-date example.
# Determining the Puppet Version
If you need to programmatically work with the Puppet version, please use the
following:
require 'puppet/version'
# Get the version baked into the sourcecode:
version = Puppet.version
# Set the version (e.g. in a Rakefile based on `git describe`)
Puppet.version = '2.3.4'
Please do not monkey patch the constant `Puppet::PUPPETVERSION` or obtain the
version using the constant. The only supported way to set and get the Puppet
version is through the accessor methods.
# Static Compiler
The static compiler was added to Puppet in the 2.7.0 release.
[1](http://links.puppetlabs.com/static-compiler-announce)
The static compiler is intended to provide a configuration catalog that
requires a minimal amount of network communication in order to apply the
catalog to the system. As implemented in Puppet 2.7.x and Puppet 3.0.x this
intention takes the form of replacing all of the source parameters of File
resources with a content parameter containing an address in the form of a
checksum. The expected behavior is that the process applying the catalog to
the node will retrieve the file content from the FileBucket instead of the
FileServer.
The high level approach can be described as follows. The `StaticCompiler` is a
terminus that inserts itself between the "normal" compiler terminus and the
request. The static compiler takes the resource catalog produced by the
compiler and filters all File resources. Any file resource that contains a
source parameter with a value starting with 'puppet://' is filtered in the
following way in a "standard" single master / networked agents deployment
scenario:
1. The content, owner, group, and mode values are retrieved from th
FileServer by the master.
2. The file content is stored in the file bucket on the master.
3. The source parameter value is stripped from the File resource.
4. The content parameter value is set in the File resource using the form
'{XXX}1234567890' which can be thought of as a content address indexed by
checksum.
5. The owner, group and mode values are set in the File resource if they are
not already set.
6. The filtered catalog is returned in the response.
In addition to the catalog terminus, the process requesting the catalog needs
to obtain the file content. The default behavior of `puppet agent` is to
obtain file contents from the local client bucket. The method we expect users
to employ to reconfigure the agent to use the server bucket is to declare the
`Filebucket[puppet]` resource with the address of the master. For example:
node default {
filebucket { puppet:
server => $server,
path => false,
}
class { filetest: }
}
This special filebucket resource named "puppet" will cause the agent to fetch
file contents specified by checksum from the remote filebucket instead of the
default clientbucket.
## Trying out the Static Compiler
Create a module that recursively downloads something. The jeffmccune-filetest
module will recursively copy the rubygems source tree.
$ bundle exec puppet module install jeffmccune-filetest
Start the master with the StaticCompiler turned on:
$ bundle exec puppet master \
--catalog_terminus=static_compiler \
--verbose \
--no-daemonize
Add the special Filebucket[puppet] resource:
# site.pp
node default {
filebucket { puppet: server => $server, path => false }
class { filetest: }
}
Get the static catalog:
$ bundle exec puppet agent --test
You should expect all file metadata to be contained in the catalog, including a
checksum representing the content. When managing an out of sync file resource,
the real contents should be fetched from the server instead of the
clientbucket.
Package Maintainers
=====
Software Version API
-----
Please see the public API regarding the software version as described in
`lib/puppet/version.rb`. Puppet provides the means to easily specify the exact
version of the software packaged using the VERSION file, for example:
$ git describe --match "3.0.*" > lib/puppet/VERSION
$ ruby -r puppet/version -e 'puts Puppet.version'
3.0.1-260-g9ca4e54
EOF

Просмотреть файл

@ -64,5 +64,5 @@ task :default do
end
task :spec do
sh %{rspec spec}
sh %{rspec #{ENV['TEST'] || ENV['TESTS'] || 'spec'}}
end

Просмотреть файл

Просмотреть файл

@ -1,6 +1,6 @@
source ENV['GEM_SOURCE'] || "https://rubygems.org"
gem "beaker", "~> 1.3.1"
gem "beaker", "~> 1.7.0"
gem "rake"
group(:test) do

Просмотреть файл

@ -10,9 +10,9 @@ module HarnessOptions
DEFAULTS = {
:type => 'git',
:helper => ['../../lib/helper.rb'],
:tests => ['../../tests'],
:debug => true,
:helper => ['lib/helper.rb'],
:tests => ['tests'],
:log_level => 'debug',
:color => false,
:root_keys => true,
:ssh => {
@ -22,6 +22,7 @@ module HarnessOptions
:timesync => true,
:repo_proxy => true,
:add_el_extras => true,
:preserve_hosts => 'onfail'
}
class Aggregator
@ -66,7 +67,9 @@ module HarnessOptions
end
def beaker_test(mode = :packages, options = {})
final_options = HarnessOptions.options(mode, options)
delete_options = options[:__delete_options__] || []
final_options = HarnessOptions.options(mode,
options.reject { |k,v| k == :__delete_options__ })
if mode == :git
puppet_fork = ENV['FORK'] || 'puppetlabs'
@ -74,6 +77,10 @@ def beaker_test(mode = :packages, options = {})
final_options[:install] << "git://#{git_server}/#{puppet_fork}/puppet.git##{sha}"
end
delete_options.each do |delete_me|
final_options.delete(delete_me)
end
options_file = 'merged_options.rb'
File.open(options_file, 'w') do |merged|
merged.puts <<-EOS
@ -92,12 +99,18 @@ EOS
args = ["--options-file", options_file, config_opt, tests_opt, overriding_options].compact
preserve_hosts = final_options[:preserve_hosts]
if md = /--preserve-hosts=?\s*['"]?(\w+)/.match(overriding_options)
preserve_hosts = md[1]
end
begin
sh("beaker", *args)
failed = false
sh("beaker", *args) { |ok,res| failed = true if !ok }
ensure
if (hosts_file = config || final_options[:hosts_file]) && hosts_file !~ /preserved_config/
cp(hosts_file, "log/latest/config.yml")
generate_config_for_latest_hosts if final_options[:preserve_hosts] || overriding_options =~ /--preserve-hosts/
generate_config_for_latest_hosts if preserve_hosts = 'always' || (failed && preserve_hosts = 'onfail')
end
mv(options_file, "log/latest")
end
@ -157,7 +170,7 @@ def list_preserved_hosts(secs_ago = ONE_DAY_IN_SECS)
File.open(log, 'r') do |file|
if file.ctime > yesterday
file.each_line do |line|
matchdata = /^(\w+) \(.*?\) \$/.match(line.encode!('UTF-8', 'UTF-8', :invalid => :replace))
matchdata = /^(\w+) \(.*?\) \d\d:\d\d:\d\d\$/.match(line.encode!('UTF-8', 'UTF-8', :invalid => :replace))
hosts.add(matchdata[1]) if matchdata
end
end
@ -166,41 +179,19 @@ def list_preserved_hosts(secs_ago = ONE_DAY_IN_SECS)
hosts
end
# Plagiarized from Beaker::Vcloud#cleanup
def destroy_preserved_hosts(hosts = nil, secs_ago = ONE_DAY_IN_SECS)
def release_hosts(hosts = nil, secs_ago = ONE_DAY_IN_SECS)
secs_ago ||= ONE_DAY_IN_SECS
hosts ||= list_preserved_hosts(secs_ago)
require 'beaker/hypervisor/vsphere_helper'
vsphere_credentials = VsphereHelper.load_config("#{ENV['HOME']}/.fog")
puts "Connecting to vSphere at #{vsphere_credentials[:server]}" +
" with credentials for #{vsphere_credentials[:user]}"
vsphere_helper = VsphereHelper.new( vsphere_credentials )
vm_names = hosts.to_a
pp vm_names
vms = vsphere_helper.find_vms vm_names
vm_names.each do |name|
unless vm = vms[name]
puts "Couldn't find VM #{name} in vSphere!"
next
end
if vm.runtime.powerState == 'poweredOn'
puts "Shutting down #{vm.name}"
start = Time.now
vm.PowerOffVM_Task.wait_for_completion
puts "Spent %.2f seconds halting #{vm.name}" % (Time.now - start)
end
start = Time.now
vm.Destroy_Task
puts "Spent %.2f seconds destroying #{vm.name}" % (Time.now - start)
end
vsphere_helper.close
require 'beaker'
vcloud_pooled = Beaker::VcloudPooled.new(hosts.map { |h| { 'vmhostname' => h } },
:logger => Beaker::Logger.new,
:dot_fog => "#{ENV['HOME']}/.fog",
'pooling_api' => 'http://vcloud.delivery.puppetlabs.net' ,
'datastore' => 'not-used',
'resourcepool' => 'not-used',
'folder' => 'not-used')
vcloud_pooled.cleanup
end
def print_preserved(preserved)
@ -269,7 +260,7 @@ Defaults to a packages run, but you can set it to 'git' with TYPE='git'.
#{USAGE}
EOS
task :test_and_preserve_hosts => 'ci:check_env' do
beaker_test(beaker_run_type, :preserve_hosts => true)
beaker_test(beaker_run_type, :preserve_hosts => 'always')
end
desc "List acceptance runs from the past day which had hosts preserved."
@ -283,19 +274,19 @@ Shutdown and destroy any hosts that we have preserved for testing. These should
Specify a list of comma separated HOST_NAMES if you have a set of dynamic vcloud host names you want to purge outside of what can be grepped from the logs.
You can go back through the last SECS_AGO logs. Default is one day ago in secs.
EOS
task :destroy_preserved_hosts do
task :release_hosts do
host_names = ENV['HOST_NAMES'].split(',') if ENV['HOST_NAMES']
secs_ago = ENV['SECS_AGO']
destroy_preserved_hosts(host_names, secs_ago)
release_hosts(host_names, secs_ago)
end
task :destroy_preserved_hosts => 'ci:release_hosts' do
puts "Note: we are now releasing hosts back to the vcloud pooling api rather than destroying them directly. The rake task for this is ci:release_hosts"
end
desc <<-EOS
Rerun an acceptance test using the last captured preserved_config.yaml to skip provisioning.
Or specify a CONFIG_NUMBER from `rake ci:list_preserved`.
Uses the setup/rsync/pre-suite to rsync the local puppet source onto master and agent.
You may specify an RSYNC_FILTER_FILE as well.
You may skip purgeing and reinstalling puppet packages by including SKIP_PACKAGE_REINSTALL.
You may skip rsyncing local puppet files over to the tests hosts by including SKIP_RSYNC.
Defaults to a packages run, but you can set it to 'git' with TYPE='git'.
EOS
task :test_against_preserved_hosts do
@ -307,8 +298,8 @@ Defaults to a packages run, but you can set it to 'git' with TYPE='git'.
beaker_test(beaker_run_type,
:hosts_file => "#{config_path}/preserved_config.yaml",
:no_provision => true,
:preserve_hosts => true,
:pre_suite => ['setup/rsync/pre-suite']
:preserve_hosts => 'always',
:__delete_options__ => [:pre_suite]
)
end
end

Просмотреть файл

@ -18,26 +18,31 @@ if [ -z $GEM_SOURCE ]; then
fi
echo "SHA: ${SHA}"
echo "FORK: ${FORK}"
echo "BUILD_SELECTOR: ${BUILD_SELECTOR}"
echo "PACKAGE_BUILD_STATUS: ${PACKAGE_BUILD_STATUS}"
rm -rf acceptance
mkdir acceptance
cd acceptance
tar -xzvf ../acceptance-artifacts.tar.gz
tar -xzf ../acceptance-artifacts.tar.gz
echo "===== This artifact is from ====="
cat creator.txt
cd config/el6
bundle install --without=development --path=.bundle/gems
if [[ "${platform}" =~ 'solaris' ]]; then
repo_proxy=" :repo_proxy => false,"
fi
cat > local_options.rb <<-EOF
{
:hosts_file => 'config/nodes/${platform}.yaml',
:ssh => {
:keys => ["${HOME}/.ssh/id_rsa-old.private"],
},
${repo_proxy}
}
EOF

16
acceptance/bin/ci-package.sh Executable file
Просмотреть файл

@ -0,0 +1,16 @@
#! /usr/bin/env bash
set -e
set -x
JOB_NAME=$1
[[ (-z "$JOB_NAME") ]] && echo "No job name passed in" && exit 1
rake --trace package:implode
rake --trace package:bootstrap
# This obtains either the sha or tag if the commit is tagged
REF=`rake pl:print_build_params |grep "^ref: " |cut -d ":" -f 2 | tr -d ' '`
rake --trace pl:jenkins:uber_build DOWNSTREAM_JOB="http://jenkins-foss.delivery.puppetlabs.net/job/$JOB_NAME/buildWithParameters?token=iheartjenkins&SHA=$REF&BUILD_SELECTOR=$BUILD_NUMBER&FORK=$GIT_FORK"
rake ci:acceptance_artifacts SHA=$REF

Просмотреть файл

@ -1,76 +0,0 @@
Local Use
=========
CI
---
There are two ways to run the ci tests locally: against packages, or against git clones.
`rake -T` will give short descriptions, and a `rake -D` will give full descriptions with information on ENV options required and optional for the various tasks.
### Authentication
Normally the ci tasks are called from a prepared Jenkins job.
If you are running this on your laptop, you will need this ssh private key in order for beaker to be able to log into the vms created from the hosts file:
https://github.com/puppetlabs/puppetlabs-modules/blob/qa/secure/jenkins/id_rsa-acceptance
https://github.com/puppetlabs/puppetlabs-modules/blob/qa/secure/jenkins/id_rsa-acceptance.pub
TODO fetch these files directly from github, but am running into rate limits and then would also have to cross the issue of authentication.
You will also need QA credentials to vsphere in a ~/.fog file. These credentials can be found on any of the Jenkins coordinator hosts.
### Packages
In order to run the tests on hosts provisioned from packages produced by Delivery, you will need to reference a Puppet commit sha that has been packaged using Delivery's pl:jenkins:uber_build task. This is the snippet used by 'Puppet Packaging' Jenkins jobs:
rake --trace package:implode
rake --trace package:bootstrap
rake --trace pl:jenkins:uber_build
The above Rake tasks were run from the root of a Puppet checkout. They are quoted just for reference. Typically if you are investigating a failure, you will have a SHA from a failed jenkins run which should correspond to a successful pipeline run, and you should not need to run the pipeline manually.
A finished pipeline will have repository information available at http://builds.puppetlabs.lan/puppet/ So you can also browse this list and select a recent sha which has repo_configs/ available.
When executing the ci:test:packages task, you must set the SHA, and also set CONFIG to point to a valid Beaker hosts_file. Configurations used in the Jenkins jobs are available under config/nodes
bundle exec rake ci:test:packages SHA=abcdef CONFIG=config/nodes/rhel.yaml
Optionally you may set the TEST (TEST=a/test.rb,and/another/test.rb), and may pass additional OPTIONS to beaker (OPTIONS='--opt foo').
You may also edit a ./local_options.rb hash which will override config/ options, and in turn be oferriden by commandline options set in the environment variables CONFIG, TEST and OPTIONS. This file is a ruby file containing a Ruby hash with configuration expected by Beaker. See Beaker source, and examples in config/.
### Git
Alternatively you may provision via git clone by calling the ci:test:git task. Currently we don't have packages for Windows or Solaris from the Delivery pipeline, and must use ci:test:git to privision and test these platforms.
### Preserving Hosts
If you have local changes to puppet code (outside of acceptance/) that you don't want to repackage for time reasons, or you just want to ssh into the hosts after a test run, you can use the following sequence:
bundle exec rake ci:test_and_preserve_hosts CONFIG=some/config.yaml SHA=12345 TEST=a/foo_test.rb
to get the initial templates provisioned, and a local log/latest/preserve_config.yaml created for them.
Then you can log into the hosts, or rerun tests against them by:
bundle exec rake ci:test_against_preserved_hosts TEST=a/foo_test.rb
This will use the existing hosts, uninstall and reinstall the puppet packages and rsync in any changes from your local source lib dir. To skip reinstalling the packages set SKIP_PACKAGE_REINSTALL=1. To skip rsyncing, set SKIP_RSYNC=1. To use rsync filters, create a file with your rsync filter settings and set RSYNC_FILTER_FILE to the name of that file. For example:
include puppet
include puppet/defaults.rb
exclude *
will ensure that only puppet/defaults.rb is copied.
NOTE: By default these tasks provision with packages. Set TYPE=git to use source checkouts.
### Cleaning Up Preserved Hosts
If you run a number of jobs with --preserve_hosts or vi ci:test_and_preserve_hosts, you may eventually generate a large number of stale vms. They should be reaped automatically by qa infrastructure within a day or so, but you may also run:
bundle exec ci:destroy_preserved_hosts
to clean them up sooner and free resources.

Просмотреть файл

@ -1,7 +0,0 @@
{
:install => [
'git://github.com/puppetlabs/facter.git#stable',
'git://github.com/puppetlabs/hiera.git#stable',
],
:pre_suite => ['setup/git/pre-suite'],
}

Просмотреть файл

@ -1,3 +0,0 @@
{
:pre_suite => ['setup/packages/pre-suite'],
}

Просмотреть файл

@ -1,9 +0,0 @@
require 'puppet/acceptance/install_utils'
extend Puppet::Acceptance::InstallUtils
test_name "Stop firewall" do
hosts.each do |host|
stop_firewall_on(host)
end
end

Просмотреть файл

@ -1,6 +0,0 @@
test_name "Validate Sign Cert"
require 'puppet/acceptance/common_utils'
extend Puppet::Acceptance::CAUtils
initialize_ssl

Просмотреть файл

@ -1,10 +0,0 @@
test_name "Purge and Reinstall Packages" do
if !ENV['SKIP_PACKAGE_REINSTALL']
hosts.each do |host|
host.uninstall_package('puppet')
host.uninstall_package('puppet-common')
additional_switches = '--allow-unauthenticated' if host['platform'] =~ /debian|ubuntu/
host.install_package('puppet', additional_switches)
end
end
end

Просмотреть файл

@ -1,25 +0,0 @@
test_name "Rsync Source" do
if !ENV['SKIP_RSYNC']
hosts.each do |host|
step "rsyncing local puppet source to #{host}" do
host.install_package('rsync') if !host.check_for_package('rsync')
filter_opt = "--filter='merge #{ENV['RSYNC_FILTER_FILE']}'" if ENV['RSYNC_FILTER_FILE']
destination_dir = case host['platform']
when /debian|ubuntu/
then '/usr/lib/ruby/vendor_ruby'
when /el|centos/
then '/usr/lib/ruby/site_ruby/1.8'
when /fedora/
then '/usr/share/ruby/vendor_ruby'
else
raise "We should actually do some #{host['platform']} platform specific rsyncing here..."
end
cmd = "rsync -r --exclude '.*.swp' #{filter_opt} --size-only -i -e'ssh -i id_rsa-acceptance' ../../../lib/* root@#{host}:#{destination_dir}"
puts "RSYNC: #{cmd}"
result = `#{cmd}`
raise("Failed rsync execution:\n#{result}") if $? != 0
puts result
end
end
end
end

Просмотреть файл

@ -0,0 +1,18 @@
{
:install => [
'git://github.com/puppetlabs/facter.git#stable',
'git://github.com/puppetlabs/hiera.git#stable',
],
:pre_suite => [
'setup/git/pre-suite/000_EnvSetup.rb',
'setup/git/pre-suite/010_TestSetup.rb',
'setup/git/pre-suite/020_PuppetUserAndGroup.rb',
'setup/common/pre-suite/025_StopFirewall.rb',
'setup/git/pre-suite/030_PuppetMasterSanity.rb',
'setup/common/pre-suite/040_ValidateSignCert.rb',
'setup/git/pre-suite/050_HieraSetup.rb',
'setup/git/pre-suite/060_InstallModules.rb',
'setup/git/pre-suite/070_InstalCACerts.rb',
'setup/common/pre-suite/100_SetParser.rb',
],
}

Просмотреть файл

@ -0,0 +1,20 @@
HOSTS:
master:
roles:
- master
- agent
platform: fedora-20-x86_64
hypervisor: vcloud
template: Delivery/Quality Assurance/Templates/vCloud/fedora-20-x86_64
agent:
roles:
- agent
platform: fedora-20-i386
hypervisor: vcloud
template: Delivery/Quality Assurance/Templates/vCloud/fedora-20-i386
CONFIG:
filecount: 12
datastore: instance0
resourcepool: delivery/Quality Assurance/FOSS/Dynamic
folder: Delivery/Quality Assurance/FOSS/Dynamic
pooling_api: http://vcloud.delivery.puppetlabs.net/

Просмотреть файл

@ -0,0 +1,20 @@
HOSTS:
master:
roles:
- master
- agent
platform: el-7-x86_64
hypervisor: vcloud
template: Delivery/Quality Assurance/Templates/vCloud/redhat-7-x86_64
agent:
roles:
- agent
platform: el-7-x86_64
hypervisor: vcloud
template: Delivery/Quality Assurance/Templates/vCloud/redhat-7-x86_64
CONFIG:
filecount: 12
datastore: instance0
resourcepool: delivery/Quality Assurance/FOSS/Dynamic
folder: Delivery/Quality Assurance/FOSS/Dynamic
pooling_api: http://vcloud.delivery.puppetlabs.net/

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше