puppet 4.4.2 → 4.5.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- data/CONTRIBUTING.md +5 -5
- data/Gemfile +2 -2
- data/LICENSE +2 -2
- data/README.md +5 -0
- data/ext/project_data.yaml +2 -0
- data/lib/hiera_puppet.rb +6 -14
- data/lib/puppet/application/agent.rb +2 -3
- data/lib/puppet/data_providers/hiera_config.rb +2 -4
- data/lib/puppet/data_providers/hiera_interpolate.rb +12 -154
- data/lib/puppet/data_providers/json_data_provider_factory.rb +0 -7
- data/lib/puppet/data_providers/yaml_data_provider_factory.rb +2 -8
- data/lib/puppet/defaults.rb +70 -7
- data/lib/puppet/functions.rb +69 -0
- data/lib/puppet/functions/dig.rb +39 -0
- data/lib/puppet/functions/lest.rb +53 -0
- data/lib/puppet/functions/lookup.rb +40 -27
- data/lib/puppet/functions/new.rb +502 -0
- data/lib/puppet/functions/regsubst.rb +11 -10
- data/lib/puppet/functions/then.rb +74 -0
- data/lib/puppet/functions/type.rb +4 -4
- data/lib/puppet/functions/with.rb +1 -1
- data/lib/puppet/indirector/catalog/compiler.rb +2 -0
- data/lib/puppet/indirector/resource_type/parser.rb +5 -0
- data/lib/puppet/indirector/rest.rb +5 -1
- data/lib/puppet/loaders.rb +2 -0
- data/lib/puppet/metatype/manager.rb +19 -2
- data/lib/puppet/module_tool/applications/application.rb +1 -1
- data/lib/puppet/module_tool/skeleton/templates/generator/Gemfile +6 -2
- data/lib/puppet/module_tool/skeleton/templates/generator/Rakefile +19 -4
- data/lib/puppet/module_tool/skeleton/templates/generator/{tests → examples}/init.pp.erb +1 -1
- data/lib/puppet/module_tool/skeleton/templates/generator/spec/classes/init_spec.rb.erb +0 -1
- data/lib/puppet/network/http/api/master/v3/environment.rb +6 -2
- data/lib/puppet/parser/ast/pops_bridge.rb +20 -3
- data/lib/puppet/parser/compiler/catalog_validator/relationship_validator.rb +24 -2
- data/lib/puppet/parser/e4_parser_adapter.rb +13 -12
- data/lib/puppet/parser/environment_compiler.rb +2 -2
- data/lib/puppet/parser/resource.rb +14 -5
- data/lib/puppet/parser/scope.rb +18 -15
- data/lib/puppet/plugins/data_providers/data_provider.rb +19 -8
- data/lib/puppet/pops.rb +6 -0
- data/lib/puppet/pops/adapters.rb +5 -1
- data/lib/puppet/pops/evaluator/access_operator.rb +52 -14
- data/lib/puppet/pops/evaluator/compare_operator.rb +34 -4
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +75 -22
- data/lib/puppet/pops/evaluator/literal_evaluator.rb +7 -6
- data/lib/puppet/pops/evaluator/runtime3_converter.rb +13 -1
- data/lib/puppet/pops/evaluator/runtime3_support.rb +14 -4
- data/lib/puppet/pops/functions/dispatcher.rb +1 -1
- data/lib/puppet/pops/issues.rb +18 -2
- data/lib/puppet/pops/loader/base_loader.rb +48 -7
- data/lib/puppet/pops/loader/dependency_loader.rb +27 -2
- data/lib/puppet/pops/loader/loader.rb +12 -0
- data/lib/puppet/pops/loader/predefined_loader.rb +29 -0
- data/lib/puppet/pops/loader/runtime3_type_loader.rb +57 -0
- data/lib/puppet/pops/loader/static_loader.rb +92 -5
- data/lib/puppet/pops/loader/type_definition_instantiator.rb +25 -3
- data/lib/puppet/pops/loaders.rb +84 -14
- data/lib/puppet/pops/lookup/explainer.rb +38 -1
- data/lib/puppet/pops/lookup/interpolation.rb +115 -0
- data/lib/puppet/pops/lookup/sub_lookup.rb +86 -0
- data/lib/puppet/pops/model/ast_transformer.rb +8 -1
- data/lib/puppet/pops/model/factory.rb +31 -8
- data/lib/puppet/pops/model/model.rb +8 -0
- data/lib/puppet/pops/model/model_label_provider.rb +1 -0
- data/lib/puppet/pops/model/model_meta.rb +7 -1
- data/lib/puppet/pops/model/model_tree_dumper.rb +4 -0
- data/lib/puppet/pops/parser/egrammar.ra +24 -7
- data/lib/puppet/pops/parser/eparser.rb +863 -798
- data/lib/puppet/pops/parser/evaluating_parser.rb +4 -0
- data/lib/puppet/pops/parser/locator.rb +8 -4
- data/lib/puppet/pops/pcore.rb +30 -0
- data/lib/puppet/pops/types/class_loader.rb +2 -4
- data/lib/puppet/pops/types/implementation_registry.rb +146 -0
- data/lib/puppet/pops/types/iterable.rb +4 -4
- data/lib/puppet/pops/types/p_object_type.rb +846 -0
- data/lib/puppet/pops/types/p_runtime_type.rb +102 -0
- data/lib/puppet/pops/types/p_sem_ver_range_type.rb +164 -0
- data/lib/puppet/pops/types/p_sem_ver_type.rb +113 -0
- data/lib/puppet/pops/types/puppet_object.rb +21 -0
- data/lib/puppet/pops/types/ruby_generator.rb +258 -0
- data/lib/puppet/pops/types/string_converter.rb +922 -0
- data/lib/puppet/pops/types/type_calculator.rb +29 -5
- data/lib/puppet/pops/types/type_conversion_error.rb +15 -0
- data/lib/puppet/pops/types/type_factory.rb +49 -16
- data/lib/puppet/pops/types/type_formatter.rb +335 -112
- data/lib/puppet/pops/types/type_mismatch_describer.rb +110 -29
- data/lib/puppet/pops/types/type_parser.rb +205 -197
- data/lib/puppet/pops/types/types.rb +481 -103
- data/lib/puppet/pops/validation.rb +1 -1
- data/lib/puppet/pops/validation/checker4_0.rb +66 -4
- data/lib/puppet/pops/validation/validator_factory_4_0.rb +1 -0
- data/lib/puppet/pops/visitor.rb +3 -1
- data/lib/puppet/property.rb +1 -1
- data/lib/puppet/provider/augeas/augeas.rb +1 -1
- data/lib/puppet/provider/package/pip.rb +64 -20
- data/lib/puppet/provider/package/rpm.rb +112 -0
- data/lib/puppet/provider/package/yum.rb +7 -68
- data/lib/puppet/provider/service/daemontools.rb +3 -3
- data/lib/puppet/provider/service/init.rb +4 -2
- data/lib/puppet/provider/service/runit.rb +3 -3
- data/lib/puppet/provider/service/smf.rb +6 -3
- data/lib/puppet/provider/service/systemd.rb +59 -73
- data/lib/puppet/reference/providers.rb +1 -2
- data/lib/puppet/resource.rb +54 -37
- data/lib/puppet/resource/catalog.rb +31 -29
- data/lib/puppet/resource/type_collection.rb +23 -8
- data/lib/puppet/settings.rb +4 -2
- data/lib/puppet/settings/base_setting.rb +9 -3
- data/lib/puppet/settings/symbolic_enum_setting.rb +17 -0
- data/lib/puppet/test/test_helper.rb +0 -1
- data/lib/puppet/type.rb +9 -3
- data/lib/puppet/type/exec.rb +17 -17
- data/lib/puppet/type/file.rb +12 -0
- data/lib/puppet/type/file/content.rb +6 -6
- data/lib/puppet/type/file/ensure.rb +4 -4
- data/lib/puppet/type/file/source.rb +4 -4
- data/lib/puppet/type/file/target.rb +2 -2
- data/lib/puppet/type/mount.rb +18 -1
- data/lib/puppet/type/package.rb +3 -3
- data/lib/puppet/type/schedule.rb +4 -4
- data/lib/puppet/type/service.rb +15 -0
- data/lib/puppet/type/sshkey.rb +5 -3
- data/lib/puppet/type/tidy.rb +3 -3
- data/lib/puppet/type/zone.rb +5 -5
- data/lib/puppet/util/feature.rb +1 -1
- data/lib/puppet/util/monkey_patches.rb +8 -0
- data/lib/puppet/util/network_device/cisco/device.rb +16 -6
- data/lib/puppet/util/network_device/cisco/interface.rb +5 -6
- data/lib/puppet/util/plist.rb +3 -3
- data/lib/puppet/version.rb +1 -1
- data/spec/fixtures/unit/application/environments/production/data/common.yaml +13 -0
- data/spec/fixtures/unit/data_providers/environments/production/modules/abc/lib/puppet/functions/abc/data.rb +2 -1
- data/spec/fixtures/unit/data_providers/environments/production/modules/abc/manifests/init.pp +2 -1
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/data/empty_key.json +1 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/hiera.yaml +5 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/manifests/init.pp +2 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/metadata.json +9 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/data/empty_key.yaml +1 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/hiera.yaml +5 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/manifests/init.pp +2 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/metadata.json +9 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_yaml/data/empty.yaml +1 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee/lib/puppet/type/usee_type.rb +5 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/manifests/init.pp +6 -0
- data/spec/fixtures/unit/provider/service/smf/svcs.out +4 -3
- data/spec/integration/module_tool/tar/mini_spec.rb +27 -27
- data/spec/integration/parser/catalog_spec.rb +14 -2
- data/spec/integration/parser/compiler_spec.rb +94 -3
- data/spec/integration/parser/resource_expressions_spec.rb +1 -1
- data/spec/integration/resource/type_collection_spec.rb +8 -0
- data/spec/lib/puppet_spec/compiler.rb +11 -4
- data/spec/shared_contexts/types_setup.rb +4 -0
- data/spec/unit/application/lookup_spec.rb +91 -9
- data/spec/unit/appmgmt_spec.rb +44 -35
- data/spec/unit/capability_spec.rb +33 -53
- data/spec/unit/data_providers/function_data_provider_spec.rb +19 -1
- data/spec/unit/data_providers/hiera_data_provider_spec.rb +1 -1
- data/spec/unit/defaults_spec.rb +18 -0
- data/spec/unit/functions/assert_type_spec.rb +1 -1
- data/spec/unit/functions/dig_spec.rb +58 -0
- data/spec/unit/functions/lest_spec.rb +34 -0
- data/spec/unit/functions/lookup_spec.rb +108 -2
- data/spec/unit/functions/new_spec.rb +543 -0
- data/spec/unit/functions/regsubst_spec.rb +8 -0
- data/spec/unit/functions/then_spec.rb +40 -0
- data/spec/unit/functions4_spec.rb +78 -10
- data/spec/unit/hiera_puppet_spec.rb +49 -8
- data/spec/unit/indirector/resource_type/parser_spec.rb +5 -0
- data/spec/unit/indirector/rest_spec.rb +12 -0
- data/spec/unit/network/http/api/master/v3/environment_spec.rb +60 -0
- data/spec/unit/node/environment_spec.rb +10 -0
- data/spec/unit/parser/compiler_spec.rb +20 -1
- data/spec/unit/parser/functions/create_resources_spec.rb +2 -2
- data/spec/unit/parser/functions/shared.rb +1 -1
- data/spec/unit/parser/resource_spec.rb +8 -1
- data/spec/unit/parser/scope_spec.rb +45 -0
- data/spec/unit/pops/evaluator/access_ops_spec.rb +14 -0
- data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +13 -5
- data/spec/unit/pops/loaders/static_loader_spec.rb +92 -1
- data/spec/unit/{data_providers/hiera_interpolation_spec.rb → pops/lookup/interpolation_spec.rb} +7 -5
- data/spec/unit/pops/parser/lexer2_spec.rb +2 -9
- data/spec/unit/pops/parser/parse_application_spec.rb +3 -8
- data/spec/unit/pops/parser/parse_basic_expressions_spec.rb +19 -0
- data/spec/unit/pops/parser/parse_capabilities_spec.rb +3 -10
- data/spec/unit/pops/parser/parse_site_spec.rb +19 -10
- data/spec/unit/pops/parser/parser_rspec_helper.rb +0 -4
- data/spec/unit/pops/types/enumeration_spec.rb +13 -12
- data/spec/unit/pops/types/iterable_spec.rb +2 -2
- data/spec/unit/pops/types/p_object_type_spec.rb +1060 -0
- data/spec/unit/pops/types/p_sem_ver_type_spec.rb +285 -0
- data/spec/unit/pops/types/recursion_guard_spec.rb +19 -17
- data/spec/unit/pops/types/ruby_generator_spec.rb +261 -0
- data/spec/unit/pops/types/string_converter_spec.rb +904 -0
- data/spec/unit/pops/types/type_calculator_spec.rb +430 -406
- data/spec/unit/pops/types/type_factory_spec.rb +119 -104
- data/spec/unit/pops/types/type_formatter_spec.rb +73 -6
- data/spec/unit/pops/types/type_mismatch_describer_spec.rb +2 -2
- data/spec/unit/pops/types/type_parser_spec.rb +54 -15
- data/spec/unit/pops/types/types_spec.rb +113 -8
- data/spec/unit/pops/validator/validator_spec.rb +84 -10
- data/spec/unit/provider/package/pip3_spec.rb +9 -270
- data/spec/unit/provider/package/pip_spec.rb +85 -30
- data/spec/unit/provider/package/rpm_spec.rb +160 -3
- data/spec/unit/provider/package/yum_spec.rb +23 -134
- data/spec/unit/provider/service/smf_spec.rb +14 -2
- data/spec/unit/provider/service/systemd_spec.rb +33 -41
- data/spec/unit/resource/capability_finder_spec.rb +10 -2
- data/spec/unit/settings/file_setting_spec.rb +6 -0
- data/spec/unit/transaction/additional_resource_generator_spec.rb +80 -65
- data/spec/unit/type/mount_spec.rb +51 -10
- data/spec/unit/type/service_spec.rb +16 -0
- data/spec/unit/type_spec.rb +14 -0
- data/spec/unit/util/feature_spec.rb +1 -1
- data/spec/unit/util/monkey_patches_spec.rb +60 -0
- data/spec/unit/util/network_device/cisco/device_spec.rb +1 -1
- metadata +63 -11
- data/lib/puppet/pops/types/types_meta.rb +0 -0
- data/spec/integration/provider/package_spec.rb +0 -35
@@ -126,7 +126,7 @@ module Validation
|
|
126
126
|
#
|
127
127
|
def []=(issue, level)
|
128
128
|
raise Puppet::DevError.new("Attempt to set validation severity for something that is not an Issue. (Got #{issue.class})") unless issue.is_a? Issues::Issue
|
129
|
-
raise Puppet::DevError.new("Illegal severity level: #{
|
129
|
+
raise Puppet::DevError.new("Illegal severity level: #{level} for '#{issue.issue_code}'") unless @@severity_hash[level]
|
130
130
|
raise Puppet::DevError.new("Attempt to demote the hard issue '#{issue.issue_code}' to #{level}") unless issue.demotable? || level == :error
|
131
131
|
@severities[issue] = level
|
132
132
|
end
|
@@ -11,7 +11,7 @@ module Validation
|
|
11
11
|
# Model objects via their metamodel. (I.e an extra call to multiplicity check in polymorph check).
|
12
12
|
# This is however mostly valuable when validating model to model transformations, and is therefore T.B.D
|
13
13
|
#
|
14
|
-
class Checker4_0
|
14
|
+
class Checker4_0 < Evaluator::LiteralEvaluator
|
15
15
|
attr_reader :acceptor
|
16
16
|
attr_reader :migration_checker
|
17
17
|
|
@@ -19,6 +19,7 @@ class Checker4_0
|
|
19
19
|
# `:will_accept?` and `:accept`.
|
20
20
|
#
|
21
21
|
def initialize(diagnostics_producer)
|
22
|
+
super()
|
22
23
|
@@check_visitor ||= Visitor.new(nil, "check", 0, 0)
|
23
24
|
@@rvalue_visitor ||= Visitor.new(nil, "rvalue", 0, 0)
|
24
25
|
@@hostname_visitor ||= Visitor.new(nil, "hostname", 1, 2)
|
@@ -235,7 +236,13 @@ class Checker4_0
|
|
235
236
|
end
|
236
237
|
|
237
238
|
def check_CallNamedFunctionExpression(o)
|
238
|
-
|
239
|
+
functor = o.functor_expr
|
240
|
+
if functor.is_a?(Model::QualifiedReference) ||
|
241
|
+
functor.is_a?(Model::AccessExpression) && functor.left_expr.is_a?(Model::QualifiedReference)
|
242
|
+
# ok (a call to a type)
|
243
|
+
return nil
|
244
|
+
end
|
245
|
+
case functor
|
239
246
|
when Model::QualifiedName
|
240
247
|
# ok
|
241
248
|
nil
|
@@ -355,6 +362,50 @@ class Checker4_0
|
|
355
362
|
internal_check_type_ref(o, o.type_expr)
|
356
363
|
end
|
357
364
|
|
365
|
+
def check_TypeMapping(o)
|
366
|
+
top(o.eContainer, o)
|
367
|
+
lhs = o.type_expr
|
368
|
+
lhs_type = 0 # Not Runtime
|
369
|
+
if lhs.is_a?(Model::AccessExpression)
|
370
|
+
left = lhs.left_expr
|
371
|
+
if left.is_a?(Model::QualifiedReference) && left.cased_value == 'Runtime'
|
372
|
+
lhs_type = 1 # Runtime
|
373
|
+
keys = lhs.keys
|
374
|
+
|
375
|
+
# Must be a literal string or pattern replacement
|
376
|
+
lhs_type = 2 if keys.size == 2 && pattern_with_replacement?(keys[1])
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
if lhs_type == 0
|
381
|
+
# This is not a TypeMapping. Something other than Runtime[] on LHS
|
382
|
+
acceptor.accept(Issues::UNSUPPORTED_EXPRESSION, o)
|
383
|
+
else
|
384
|
+
rhs = o.mapping_expr
|
385
|
+
if pattern_with_replacement?(rhs)
|
386
|
+
acceptor.accept(Issues::ILLEGAL_SINGLE_TYPE_MAPPING, o) if lhs_type == 1
|
387
|
+
elsif type_ref?(rhs)
|
388
|
+
acceptor.accept(Issues::ILLEGAL_REGEXP_TYPE_MAPPING, o) if lhs_type == 2
|
389
|
+
else
|
390
|
+
acceptor.accept(lhs_type == 1 ? Issues::ILLEGAL_SINGLE_TYPE_MAPPING : Issues::ILLEGAL_REGEXP_TYPE_MAPPING, o)
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
def pattern_with_replacement?(o)
|
396
|
+
if o.is_a?(Model::LiteralList)
|
397
|
+
v = o.values
|
398
|
+
v.size == 2 && v[0].is_a?(Model::LiteralRegularExpression) && v[1].is_a?(Model::LiteralString)
|
399
|
+
else
|
400
|
+
false
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
def type_ref?(o)
|
405
|
+
o = o.left_expr if o.is_a?(Model::AccessExpression)
|
406
|
+
o.is_a?(Model::QualifiedReference)
|
407
|
+
end
|
408
|
+
|
358
409
|
def check_TypeDefinition(o)
|
359
410
|
top(o.eContainer, o)
|
360
411
|
internal_check_reserved_type_name(o, o.name)
|
@@ -467,6 +518,17 @@ class Checker4_0
|
|
467
518
|
o.values.each {|v| rvalue(v) }
|
468
519
|
end
|
469
520
|
|
521
|
+
def check_LiteralHash(o)
|
522
|
+
# the keys of a literal hash may be non-literal expressions. They cannot be checked.
|
523
|
+
unique = Set.new
|
524
|
+
o.entries.each do |entry|
|
525
|
+
catch(:not_literal) do
|
526
|
+
literal_key = literal(entry.key)
|
527
|
+
acceptor.accept(Issues::DUPLICATE_KEY, entry, {:key => literal_key}) if unique.add?(literal_key).nil?
|
528
|
+
end
|
529
|
+
end
|
530
|
+
end
|
531
|
+
|
470
532
|
def check_NodeDefinition(o)
|
471
533
|
# Check that hostnames are valid hostnames (or regular expressions)
|
472
534
|
hostname(o.host_matches, o)
|
@@ -491,8 +553,8 @@ class Checker4_0
|
|
491
553
|
# DOH: QualifiedReferences are created with LOWER CASE NAMES at parse time
|
492
554
|
def check_QualifiedReference(o)
|
493
555
|
# Is this a valid qualified name?
|
494
|
-
if o.
|
495
|
-
acceptor.accept(Issues::ILLEGAL_CLASSREF, o, {:name=>o.
|
556
|
+
if o.cased_value !~ Patterns::CLASSREF_EXT
|
557
|
+
acceptor.accept(Issues::ILLEGAL_CLASSREF, o, {:name=>o.cased_value})
|
496
558
|
end
|
497
559
|
end
|
498
560
|
|
@@ -27,6 +27,7 @@ class ValidatorFactory_4_0 < Factory
|
|
27
27
|
|
28
28
|
p[Issues::FUTURE_RESERVED_WORD] = :deprecation
|
29
29
|
|
30
|
+
p[Issues::DUPLICATE_KEY] = Puppet[:strict] == :off ? :ignore : Puppet[:strict]
|
30
31
|
p[Issues::NAME_WITH_HYPHEN] = :error
|
31
32
|
p[Issues::EMPTY_RESOURCE_SPECIALIZATION] = :ignore
|
32
33
|
p
|
data/lib/puppet/pops/visitor.rb
CHANGED
@@ -40,7 +40,9 @@ class Puppet::Pops::Visitor
|
|
40
40
|
return receiver.send(method_name, thing, *args)
|
41
41
|
else
|
42
42
|
thing.class.ancestors().each do |ancestor|
|
43
|
-
|
43
|
+
name = ancestor.name
|
44
|
+
next if name.nil?
|
45
|
+
method_name = :"#{@message}_#{name.split(DOUBLE_COLON).last}"
|
44
46
|
next unless receiver.respond_to?(method_name, true)
|
45
47
|
@cache[thing.class] = method_name
|
46
48
|
return receiver.send(method_name, thing, *args)
|
data/lib/puppet/property.rb
CHANGED
@@ -521,7 +521,7 @@ class Puppet::Property < Puppet::Parameter
|
|
521
521
|
if features = self.class.value_option(self.class.value_name(value), :required_features)
|
522
522
|
features = Array(features)
|
523
523
|
needed_features = features.collect { |f| f.to_s }.join(", ")
|
524
|
-
raise ArgumentError, "Provider must have features '#{needed_features}' to set '#{self.class.name}' to '#{value}'" unless provider.satisfies?(features)
|
524
|
+
raise ArgumentError, "Provider #{provider.class.name} must have features '#{needed_features}' to set '#{self.class.name}' to '#{value}'" unless provider.satisfies?(features)
|
525
525
|
end
|
526
526
|
end
|
527
527
|
|
@@ -425,7 +425,7 @@ Puppet::Type.type(:augeas).provide(:augeas) do
|
|
425
425
|
end
|
426
426
|
|
427
427
|
unless force
|
428
|
-
# If we have a
|
428
|
+
# If we have a version of augeas which is at least 0.3.6 then we
|
429
429
|
# can make the changes now and see if changes were made.
|
430
430
|
if return_value and versioncmp(get_augeas_version, "0.3.6") >= 0
|
431
431
|
debug("Will attempt to save and only run if files changed")
|
@@ -30,7 +30,7 @@ Puppet::Type.type(:package).provide :pip,
|
|
30
30
|
# that's managed by `pip` or an empty array if `pip` is not available.
|
31
31
|
def self.instances
|
32
32
|
packages = []
|
33
|
-
pip_cmd =
|
33
|
+
pip_cmd = self.pip_cmd
|
34
34
|
return [] unless pip_cmd
|
35
35
|
execpipe "#{pip_cmd} freeze" do |process|
|
36
36
|
process.collect do |line|
|
@@ -38,6 +38,13 @@ Puppet::Type.type(:package).provide :pip,
|
|
38
38
|
packages << new(options)
|
39
39
|
end
|
40
40
|
end
|
41
|
+
|
42
|
+
# Pip can also upgrade pip, but it's not listed in freeze so need to special case it
|
43
|
+
# Pip list would also show pip installed version, but "pip list" doesn't exist for older versions of pip (E.G v1.0)
|
44
|
+
if version = self.pip_version
|
45
|
+
packages << new({:ensure => version, :name => File.basename(pip_cmd), :provider => name})
|
46
|
+
end
|
47
|
+
|
41
48
|
packages
|
42
49
|
end
|
43
50
|
|
@@ -45,6 +52,21 @@ Puppet::Type.type(:package).provide :pip,
|
|
45
52
|
["pip", "pip-python"]
|
46
53
|
end
|
47
54
|
|
55
|
+
def self.pip_cmd
|
56
|
+
self.cmd.map { |c| which(c) }.find { |c| c != nil }
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.pip_version
|
60
|
+
pip_cmd = self.pip_cmd
|
61
|
+
return nil unless pip_cmd
|
62
|
+
|
63
|
+
execpipe [pip_cmd, '--version'] do |process|
|
64
|
+
process.collect do |line|
|
65
|
+
return line.strip.match(/^pip (\d+\.\d+\.?\d*).*$/)[1]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
48
70
|
# Return structured information about a particular package or `nil` if
|
49
71
|
# it is not installed or `pip` itself is not available.
|
50
72
|
def query
|
@@ -54,26 +76,13 @@ Puppet::Type.type(:package).provide :pip,
|
|
54
76
|
return nil
|
55
77
|
end
|
56
78
|
|
57
|
-
#
|
58
|
-
# cache of PyPI's package list so this operation will always have to
|
59
|
-
# ask the web service.
|
79
|
+
# Use pip CLI to look up versions from PyPI repositories, honoring local pip config such as custom repositories
|
60
80
|
def latest
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
proxy = "#{http_proxy_host}:#{http_proxy_port}"
|
65
|
-
else
|
66
|
-
# nil is acceptable
|
67
|
-
proxy = http_proxy_host
|
81
|
+
return nil unless self.class.pip_cmd
|
82
|
+
if Puppet::Util::Package.versioncmp(self.class.pip_version, '1.5.4') == -1 # a < b
|
83
|
+
return latest_with_old_pip
|
68
84
|
end
|
69
|
-
|
70
|
-
client = XMLRPC::Client.new2("http://pypi.python.org/pypi", proxy)
|
71
|
-
client.http_header_extra = {"Content-Type" => "text/xml"}
|
72
|
-
client.timeout = 10
|
73
|
-
result = client.call("package_releases", @resource[:name])
|
74
|
-
result.first
|
75
|
-
rescue Timeout::Error => detail
|
76
|
-
raise Puppet::Error, "Timeout while contacting pypi.python.org: #{detail}", detail.backtrace
|
85
|
+
latest_with_new_pip
|
77
86
|
end
|
78
87
|
|
79
88
|
# Install a package. The ensure parameter may specify installed,
|
@@ -120,8 +129,14 @@ Puppet::Type.type(:package).provide :pip,
|
|
120
129
|
def lazy_pip(*args)
|
121
130
|
pip *args
|
122
131
|
rescue NoMethodError => e
|
132
|
+
# Ensure pip can upgrade pip, which usually puts pip into a new path /usr/local/bin/pip (compared to /usr/bin/pip)
|
133
|
+
# The path to pip needs to be looked up again in the subsequent request. Using the preferred approach as noted
|
134
|
+
# in provider.rb ensures this (copied below for reference)
|
135
|
+
#
|
136
|
+
# @note From provider.rb; It is preferred if the commands are not entered with absolute paths as this allows puppet
|
137
|
+
# to search for them using the PATH variable.
|
123
138
|
if pathname = self.class.cmd.map { |c| which(c) }.find { |c| c != nil }
|
124
|
-
self.class.commands :pip => pathname
|
139
|
+
self.class.commands :pip => File.basename(pathname)
|
125
140
|
pip *args
|
126
141
|
else
|
127
142
|
raise e, "Could not locate command #{self.class.cmd.join(' and ')}.", e.backtrace
|
@@ -131,4 +146,33 @@ Puppet::Type.type(:package).provide :pip,
|
|
131
146
|
def install_options
|
132
147
|
join_options(@resource[:install_options])
|
133
148
|
end
|
149
|
+
|
150
|
+
def latest_with_new_pip
|
151
|
+
# Less resource intensive approach for pip version 1.5.4 and above
|
152
|
+
execpipe ["#{self.class.pip_cmd}", "install", "#{@resource[:name]}==versionplease"] do |process|
|
153
|
+
process.collect do |line|
|
154
|
+
# PIP OUTPUT: Could not find a version that satisfies the requirement Django==versionplease (from versions: 1.1.3, 1.8rc1)
|
155
|
+
if line =~ /from versions: /
|
156
|
+
textAfterLastMatch = $'
|
157
|
+
versionList = textAfterLastMatch.chomp(")\n").split(', ')
|
158
|
+
return versionList.last
|
159
|
+
end
|
160
|
+
end
|
161
|
+
return nil
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def latest_with_old_pip
|
166
|
+
Dir.mktmpdir("puppet_pip") do |dir|
|
167
|
+
execpipe ["#{self.class.pip_cmd}", "install", "#{@resource[:name]}", "-d", "#{dir}", "-v"] do |process|
|
168
|
+
process.collect do |line|
|
169
|
+
# PIP OUTPUT: Using version 0.10.1 (newest of versions: 0.10.1, 0.10, 0.9, 0.8.1, 0.8, 0.7.2, 0.7.1, 0.7, 0.6.1, 0.6, 0.5.2, 0.5.1, 0.5, 0.4, 0.3.1, 0.3, 0.2, 0.1)
|
170
|
+
if line =~ /Using version (.+?) \(newest of versions/
|
171
|
+
return $1
|
172
|
+
end
|
173
|
+
end
|
174
|
+
return nil
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
134
178
|
end
|
@@ -22,6 +22,31 @@ Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Pr
|
|
22
22
|
self::NEVRA_REGEX = %r{^(\S+) (\S+) (\S+) (\S+) (\S+)$}
|
23
23
|
self::NEVRA_FIELDS = [:name, :epoch, :version, :release, :arch]
|
24
24
|
|
25
|
+
ARCH_LIST = [
|
26
|
+
'noarch',
|
27
|
+
'i386',
|
28
|
+
'i686',
|
29
|
+
'ppc',
|
30
|
+
'ppc64',
|
31
|
+
'armv3l',
|
32
|
+
'armv4b',
|
33
|
+
'armv4l',
|
34
|
+
'armv4tl',
|
35
|
+
'armv5tel',
|
36
|
+
'armv5tejl',
|
37
|
+
'armv6l',
|
38
|
+
'armv7l',
|
39
|
+
'm68kmint',
|
40
|
+
's390',
|
41
|
+
's390x',
|
42
|
+
'ia64',
|
43
|
+
'x86_64',
|
44
|
+
'sh3',
|
45
|
+
'sh4',
|
46
|
+
]
|
47
|
+
|
48
|
+
ARCH_REGEX = Regexp.new(ARCH_LIST.join('|\.'))
|
49
|
+
|
25
50
|
commands :rpm => "rpm"
|
26
51
|
|
27
52
|
if command('rpm')
|
@@ -268,6 +293,92 @@ Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Pr
|
|
268
293
|
end
|
269
294
|
end
|
270
295
|
|
296
|
+
def insync?(is)
|
297
|
+
return false if [:purged, :absent].include?(is)
|
298
|
+
should = resource[:ensure]
|
299
|
+
0 == rpm_compareEVR(rpm_parse_evr(should), rpm_parse_evr(is))
|
300
|
+
end
|
301
|
+
|
302
|
+
# parse a rpm "version" specification
|
303
|
+
# this re-implements rpm's
|
304
|
+
# rpmUtils.miscutils.stringToVersion() in ruby
|
305
|
+
def rpm_parse_evr(s)
|
306
|
+
ei = s.index(':')
|
307
|
+
if ei
|
308
|
+
e = s[0,ei]
|
309
|
+
s = s[ei+1,s.length]
|
310
|
+
else
|
311
|
+
e = nil
|
312
|
+
end
|
313
|
+
begin
|
314
|
+
e = String(Integer(e))
|
315
|
+
rescue
|
316
|
+
# If there are non-digits in the epoch field, default to nil
|
317
|
+
e = nil
|
318
|
+
end
|
319
|
+
ri = s.index('-')
|
320
|
+
if ri
|
321
|
+
v = s[0,ri]
|
322
|
+
r = s[ri+1,s.length]
|
323
|
+
if arch = r.scan(ARCH_REGEX)[0]
|
324
|
+
a = arch.gsub(/\./, '')
|
325
|
+
r.gsub!(ARCH_REGEX, '')
|
326
|
+
end
|
327
|
+
else
|
328
|
+
v = s
|
329
|
+
r = nil
|
330
|
+
end
|
331
|
+
return { :epoch => e, :version => v, :release => r, :arch => a }
|
332
|
+
end
|
333
|
+
|
334
|
+
# how rpm compares two package versions:
|
335
|
+
# rpmUtils.miscutils.compareEVR(), which massages data types and then calls
|
336
|
+
# rpm.labelCompare(), found in rpm.git/python/header-py.c, which
|
337
|
+
# sets epoch to 0 if null, then compares epoch, then ver, then rel
|
338
|
+
# using compare_values() and returns the first non-0 result, else 0.
|
339
|
+
# This function combines the logic of compareEVR() and labelCompare().
|
340
|
+
#
|
341
|
+
# "version_should" can be v, v-r, or e:v-r.
|
342
|
+
# "version_is" will always be at least v-r, can be e:v-r
|
343
|
+
def rpm_compareEVR(should_hash, is_hash)
|
344
|
+
# pass on to rpm labelCompare
|
345
|
+
|
346
|
+
if !should_hash[:epoch].nil?
|
347
|
+
rc = compare_values(should_hash[:epoch], is_hash[:epoch])
|
348
|
+
return rc unless rc == 0
|
349
|
+
end
|
350
|
+
|
351
|
+
rc = compare_values(should_hash[:version], is_hash[:version])
|
352
|
+
return rc unless rc == 0
|
353
|
+
|
354
|
+
# here is our special case, PUP-1244.
|
355
|
+
# if should_hash[:release] is nil (not specified by the user),
|
356
|
+
# and comparisons up to here are equal, return equal. We need to
|
357
|
+
# evaluate to whatever level of detail the user specified, so we
|
358
|
+
# don't end up upgrading or *downgrading* when not intended.
|
359
|
+
#
|
360
|
+
# This should NOT be triggered if we're trying to ensure latest.
|
361
|
+
return 0 if should_hash[:release].nil?
|
362
|
+
|
363
|
+
rc = compare_values(should_hash[:release], is_hash[:release])
|
364
|
+
|
365
|
+
return rc
|
366
|
+
end
|
367
|
+
|
368
|
+
# this method is a native implementation of the
|
369
|
+
# compare_values function in rpm's python bindings,
|
370
|
+
# found in python/header-py.c, as used by rpm.
|
371
|
+
def compare_values(s1, s2)
|
372
|
+
if s1.nil? && s2.nil?
|
373
|
+
return 0
|
374
|
+
elsif ( not s1.nil? ) && s2.nil?
|
375
|
+
return 1
|
376
|
+
elsif s1.nil? && (not s2.nil?)
|
377
|
+
return -1
|
378
|
+
end
|
379
|
+
return rpmvercmp(s1, s2)
|
380
|
+
end
|
381
|
+
|
271
382
|
private
|
272
383
|
# @param line [String] one line of rpm package query information
|
273
384
|
# @return [Hash] of NEVRA_FIELDS strings parsed from package info
|
@@ -281,6 +392,7 @@ Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Pr
|
|
281
392
|
self::NEVRA_FIELDS.zip(match.captures) { |f, v| hash[f] = v }
|
282
393
|
hash[:provider] = self.name
|
283
394
|
hash[:ensure] = "#{hash[:version]}-#{hash[:release]}"
|
395
|
+
hash[:ensure].prepend("#{hash[:epoch]}:") if hash[:epoch] != '0'
|
284
396
|
else
|
285
397
|
Puppet.debug("Failed to match rpm line #{line}")
|
286
398
|
end
|
@@ -149,8 +149,13 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
|
|
149
149
|
else
|
150
150
|
# Add the package version
|
151
151
|
wanted += "-#{should}"
|
152
|
+
if wanted.scan(ARCH_REGEX)
|
153
|
+
self.debug "Detected Arch argument in package! - Moving arch to end of version string"
|
154
|
+
wanted.gsub!(/(.+)(#{ARCH_REGEX})(.+)/,'\1\3\2')
|
155
|
+
end
|
156
|
+
|
152
157
|
is = self.query
|
153
|
-
if is &&
|
158
|
+
if is && rpm_compareEVR(rpm_parse_evr(should), rpm_parse_evr(is[:ensure])) < 0
|
154
159
|
self.debug "Downgrading package #{@resource[:name]} from version #{is[:ensure]} to #{should}"
|
155
160
|
operation = :downgrade
|
156
161
|
end
|
@@ -173,7 +178,7 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
|
|
173
178
|
|
174
179
|
# FIXME: Should we raise an exception even if should == :latest
|
175
180
|
# and yum updated us to a version other than @param_hash[:ensure] ?
|
176
|
-
vercmp_result =
|
181
|
+
vercmp_result = rpm_compareEVR(rpm_parse_evr(should), rpm_parse_evr(is[:ensure]))
|
177
182
|
raise Puppet::Error, "Failed to update to version #{should}, got version #{is[:ensure]} instead" if vercmp_result != 0
|
178
183
|
end
|
179
184
|
end
|
@@ -202,72 +207,6 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
|
|
202
207
|
execute([command(:cmd), "-y", :erase, @resource[:name]])
|
203
208
|
end
|
204
209
|
|
205
|
-
# parse a yum "version" specification
|
206
|
-
# this re-implements yum's
|
207
|
-
# rpmUtils.miscutils.stringToVersion() in ruby
|
208
|
-
def yum_parse_evr(s)
|
209
|
-
ei = s.index(':')
|
210
|
-
if ei
|
211
|
-
e = s[0,ei]
|
212
|
-
s = s[ei+1,s.length]
|
213
|
-
else
|
214
|
-
e = nil
|
215
|
-
end
|
216
|
-
e = String(Bignum(e)) rescue '0'
|
217
|
-
ri = s.index('-')
|
218
|
-
if ri
|
219
|
-
v = s[0,ri]
|
220
|
-
r = s[ri+1,s.length]
|
221
|
-
else
|
222
|
-
v = s
|
223
|
-
r = nil
|
224
|
-
end
|
225
|
-
return { :epoch => e, :version => v, :release => r }
|
226
|
-
end
|
227
|
-
|
228
|
-
# how yum compares two package versions:
|
229
|
-
# rpmUtils.miscutils.compareEVR(), which massages data types and then calls
|
230
|
-
# rpm.labelCompare(), found in rpm.git/python/header-py.c, which
|
231
|
-
# sets epoch to 0 if null, then compares epoch, then ver, then rel
|
232
|
-
# using compare_values() and returns the first non-0 result, else 0.
|
233
|
-
# This function combines the logic of compareEVR() and labelCompare().
|
234
|
-
#
|
235
|
-
# "version_should" can be v, v-r, or e:v-r.
|
236
|
-
# "version_is" will always be at least v-r, can be e:v-r
|
237
|
-
def yum_compareEVR(should_hash, is_hash)
|
238
|
-
# pass on to rpm labelCompare
|
239
|
-
rc = compare_values(should_hash[:epoch], is_hash[:epoch])
|
240
|
-
return rc unless rc == 0
|
241
|
-
rc = compare_values(should_hash[:version], is_hash[:version])
|
242
|
-
return rc unless rc == 0
|
243
|
-
|
244
|
-
# here is our special case, PUP-1244.
|
245
|
-
# if should_hash[:release] is nil (not specified by the user),
|
246
|
-
# and comparisons up to here are equal, return equal. We need to
|
247
|
-
# evaluate to whatever level of detail the user specified, so we
|
248
|
-
# don't end up upgrading or *downgrading* when not intended.
|
249
|
-
#
|
250
|
-
# This should NOT be triggered if we're trying to ensure latest.
|
251
|
-
return 0 if should_hash[:release].nil?
|
252
|
-
|
253
|
-
rc = compare_values(should_hash[:release], is_hash[:release])
|
254
|
-
return rc
|
255
|
-
end
|
256
|
-
|
257
|
-
# this method is a native implementation of the
|
258
|
-
# compare_values function in rpm's python bindings,
|
259
|
-
# found in python/header-py.c, as used by yum.
|
260
|
-
def compare_values(s1, s2)
|
261
|
-
if s1.nil? && s2.nil?
|
262
|
-
return 0
|
263
|
-
elsif ( not s1.nil? ) && s2.nil?
|
264
|
-
return 1
|
265
|
-
elsif s1.nil? && (not s2.nil?)
|
266
|
-
return -1
|
267
|
-
end
|
268
|
-
return rpmvercmp(s1, s2)
|
269
|
-
end
|
270
|
-
|
271
210
|
private
|
272
211
|
|
273
212
|
def enablerepo
|