├── .gitignore ├── files ├── empty │ └── .keep └── default.rego ├── .ruby-version ├── .pdkignore ├── types ├── policy_action.pp ├── collective.pp └── policy.pp ├── data ├── os │ ├── Darwin.yaml │ ├── Archlinux.yaml │ ├── OpenBSD.yaml │ ├── FreeBSD.yaml │ └── windows.yaml └── common.yaml ├── NOTICE ├── functions └── hash2config.pp ├── templates ├── refresh_facts.timer.epp ├── refresh_facts.service.epp ├── policy_file.epp └── refresh_facts.erb ├── hiera.yaml ├── lib ├── puppet │ └── functions │ │ └── mcollective │ │ └── crontimes.rb └── facter │ └── mcollective.rb ├── README.md ├── manifests ├── plugin_dirs.pp ├── config_file.pp ├── facts.pp ├── init.pp ├── config.pp └── module_plugin.pp ├── metadata.json ├── LICENSE └── CHANGELOG.md /.gitignore: -------------------------------------------------------------------------------- 1 | pkg 2 | -------------------------------------------------------------------------------- /files/empty/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.1.9 2 | -------------------------------------------------------------------------------- /.pdkignore: -------------------------------------------------------------------------------- 1 | .git 2 | spec 3 | Gemfile* 4 | Rakefile 5 | pkg 6 | vendor 7 | -------------------------------------------------------------------------------- /types/policy_action.pp: -------------------------------------------------------------------------------- 1 | type Mcollective::Policy_action = Enum["allow", "deny"] 2 | -------------------------------------------------------------------------------- /types/collective.pp: -------------------------------------------------------------------------------- 1 | type Mcollective::Collective = Pattern[/\A[a-zA-Z0-9_-]+\Z/] 2 | -------------------------------------------------------------------------------- /data/os/Darwin.yaml: -------------------------------------------------------------------------------- 1 | mcollective::plugin_group: wheel 2 | mcollective::required_directories: [] 3 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Choria puppet-mcollective 2 | 3 | Copyright 2018 R.I.Pienaar 4 | 5 | This product includes software developed at 6 | The Choria Project (https://choria.io). 7 | -------------------------------------------------------------------------------- /types/policy.pp: -------------------------------------------------------------------------------- 1 | type Mcollective::Policy = Struct[{ 2 | "action" => Mcollective::Policy_action, 3 | "callers" => String, 4 | "actions" => String, 5 | "facts" => String, 6 | "classes" => Optional[String] 7 | }] 8 | -------------------------------------------------------------------------------- /data/os/Archlinux.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | mcollective::libdir: "/etc/puppetlabs/mcollective/plugins" 3 | mcollective::rubypath: "/usr/bin/ruby" 4 | mcollective::required_directories: 5 | - /etc/puppetlabs/mcollective 6 | mcollective::manage_bin_symlinks: false 7 | -------------------------------------------------------------------------------- /functions/hash2config.pp: -------------------------------------------------------------------------------- 1 | # Generates configuration files for mcollective. Keys are sorted alphabetically: 2 | # key = value 3 | function mcollective::hash2config(Hash $confighash) >> String { 4 | $result = $confighash.keys.sort.map |$key| { 5 | sprintf("%s = %s", $key, $confighash[$key]) 6 | } 7 | ($result << []).join("\n") 8 | } 9 | -------------------------------------------------------------------------------- /templates/refresh_facts.timer.epp: -------------------------------------------------------------------------------- 1 | <%- | 2 | String $oncalendar, 3 | | -%> 4 | # 5 | # Managed by Puppet, DO NOT EDIT 6 | # 7 | [Unit] 8 | Description=Systemd Timer for Mcollective fact refresh 9 | 10 | [Timer] 11 | OnCalendar=<%= $oncalendar %> 12 | Persistent=false 13 | RandomizedDelaySec=30 14 | 15 | [Install] 16 | WantedBy=timers.target 17 | -------------------------------------------------------------------------------- /hiera.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 5 3 | 4 | defaults: 5 | datadir: "data" 6 | data_hash: yaml_data 7 | 8 | hierarchy: 9 | - name: "OS family" 10 | path: "os/%{facts.os.family}.yaml" 11 | 12 | - name: "Puppet version specific common" 13 | path: "puppet_aio/%{facts.mcollective.puppet_major_version}.yaml" 14 | 15 | - name: "common" 16 | path: "common.yaml" 17 | -------------------------------------------------------------------------------- /lib/puppet/functions/mcollective/crontimes.rb: -------------------------------------------------------------------------------- 1 | Puppet::Functions.create_function(:'mcollective::crontimes') do 2 | dispatch :crontimes do 3 | required_param 'Integer', :offset 4 | required_param 'Integer', :interval 5 | required_param 'Integer', :period 6 | end 7 | 8 | def crontimes(offset, interval, period) 9 | (period / interval).times.map do |i| 10 | val = i * interval + offset 11 | 12 | val if val < period && val < 60 13 | end.compact 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /templates/refresh_facts.service.epp: -------------------------------------------------------------------------------- 1 | <%- | 2 | String $rubypath, 3 | String $scriptpath, 4 | String $factspath, 5 | String $pidfile, 6 | | -%> 7 | # 8 | # Managed by Puppet, DO NOT EDIT 9 | # 10 | [Unit] 11 | Description=Systemd Service for Mcollective fact refresh 12 | 13 | [Service] 14 | Type=oneshot 15 | ExecStart=<%= $rubypath %> <%= $scriptpath %> -o <%= $factspath %> -p <%= $pidfile %> 16 | PIDFile=<%= $pidfile %> 17 | User=root 18 | Group=root 19 | SyslogIdentifier=mcollective-facts-refresh 20 | -------------------------------------------------------------------------------- /files/default.rego: -------------------------------------------------------------------------------- 1 | # This is the default rego policy that will apply to all 2 | # agents that do not have a specific rego policy set. 3 | # 4 | # This particular one is from the choria/mcollective module 5 | # and you can supply the source of your own by setting the 6 | # hiera data mcollective::default_rego_policy_source to a 7 | # Puppet file source of your choice 8 | package io.choria.mcorpc.authpolicy 9 | 10 | default allow = false 11 | 12 | allow { 13 | input.agent == "rpcutil" 14 | input.action == "ping" 15 | } 16 | 17 | allow { 18 | input.agent == "choria_util" 19 | input.action == "info" 20 | } 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Manage an AIO Installation of The Marionette Collective 2 | ======================================================= 3 | 4 | This module manages a Puppet AIO based MCollective. 5 | 6 | It makes default decisions that are compatible with AIO and tries to get as 7 | close to working out of the box with no complex config or decision making needed 8 | on the side of the user. 9 | 10 | The module can be used standalone but it's designed to work with Choria - a companion 11 | suite of plugins that makes a AIO based MCollective easy to install and use. 12 | 13 | Follow the guide at the [Choria Website](http://choria.io) for installation details 14 | -------------------------------------------------------------------------------- /data/os/OpenBSD.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | mcollective::plugin_group: wheel 3 | mcollective::configdir: "/etc/choria" 4 | mcollective::bindir: "/usr/local/bin" 5 | mcollective::libdir: "/usr/local/libexec/mcollective" 6 | mcollective::rubypath: "/usr/local/bin/ruby24" 7 | mcollective::gem_provider: "gem" 8 | mcollective::required_directories: [] 9 | mcollective::manage_bin_symlinks: false 10 | 11 | mcollective::server_config: 12 | classesfile: "/var/puppetlabs/puppet/cache/state/classes.txt" 13 | rpcauthorization: 1 14 | rpcauthprovider: "action_policy" 15 | factsource: "yaml" 16 | plugin.yaml: "/etc/choria/generated-facts.yaml" 17 | logfile: "/var/log/puppetlabs/choria-mcorpc.log" 18 | daemonize: 0 19 | -------------------------------------------------------------------------------- /data/os/FreeBSD.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | mcollective::plugin_group: wheel 3 | mcollective::configdir: "/usr/local/etc/choria" 4 | mcollective::bindir: "/usr/local/bin" 5 | mcollective::libdir: "/usr/local/share/choria/plugins" 6 | mcollective::rubypath: "/usr/local/bin/ruby" 7 | mcollective::gem_provider: "gem" 8 | mcollective::required_directories: [] 9 | mcollective::manage_bin_symlinks: false 10 | mcollective::facts_pidfile: "/var/run/puppet/mcollective-facts_refresh.pid" 11 | 12 | mcollective::server_config: 13 | classesfile: "/var/puppet/state/classes.txt" 14 | rpcauthorization: 1 15 | rpcauthprovider: "action_policy" 16 | factsource: "yaml" 17 | plugin.yaml: "/usr/local/etc/choria/generated-facts.yaml" 18 | logfile: "/var/log/choria-mcorpc.log" 19 | daemonize: 0 20 | -------------------------------------------------------------------------------- /templates/policy_file.epp: -------------------------------------------------------------------------------- 1 | <%- | 2 | String $module, 3 | String $policy_default, 4 | Array[Mcollective::Policy] $policies, 5 | Array[Mcollective::Policy] $site_policies 6 | | -%> 7 | policy default <%= $policy_default %> 8 | <%- if !$policies.empty { -%> 9 | 10 | # <%= $module %> module specific policies 11 | <%- $policies.each |$policy| { -%> 12 | <%= [$policy["action"], $policy["callers"], $policy["actions"], $policy["facts"], $policy["classes"]].delete_undef_values.join("\t") %> 13 | <%- } -%> 14 | <%- } -%> 15 | <%- if !$site_policies.empty { -%> 16 | 17 | # site wide policies 18 | <%- $site_policies.each |$policy| { -%> 19 | <%= [$policy["action"], $policy["callers"], $policy["actions"], $policy["facts"], $policy["classes"]].delete_undef_values.join("\t") %> 20 | <%- } -%> 21 | <%- } -%> 22 | -------------------------------------------------------------------------------- /manifests/plugin_dirs.pp: -------------------------------------------------------------------------------- 1 | class mcollective::plugin_dirs { 2 | $libdirs = $mcollective::plugintypes.map |$type| { 3 | "${mcollective::libdir}/mcollective/${type}" 4 | } 5 | 6 | $needed_dirs = [$mcollective::libdir, "${mcollective::libdir}/mcollective"] + $libdirs 7 | 8 | if $mcollective::purge { 9 | $purge_options = { 10 | source => "puppet:///modules/mcollective/empty", 11 | ignore => ".keep", 12 | purge => true, 13 | recurse => true, 14 | force => true 15 | } 16 | } else { 17 | $purge_options = {} 18 | } 19 | 20 | file { 21 | default: 22 | * => $purge_options; 23 | 24 | $needed_dirs: 25 | ensure => "directory", 26 | owner => $mcollective::plugin_owner, 27 | group => $mcollective::plugin_group, 28 | mode => $mcollective::plugin_mode; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /data/os/windows.yaml: -------------------------------------------------------------------------------- 1 | mcollective::plugin_owner: ~ 2 | mcollective::plugin_group: ~ 3 | 4 | mcollective::facts_refresh_type: ~ 5 | mcollective::bindir: "C:/Program Files/choria/bin" 6 | mcollective::libdir: "C:/ProgramData/choria/lib/plugins" 7 | mcollective::configdir: "C:/ProgramData/choria/etc" 8 | mcollective::rubypath: "C:/Program Files/Puppet Labs/Puppet/puppet/bin/ruby.exe" 9 | mcollective::facts_pidfile: ~ 10 | mcollective::manage_bin_symlinks: false 11 | 12 | mcollective::required_directories: 13 | - "C:/ProgramData/choria" 14 | - "C:/ProgramData/choria/lib" 15 | - "C:/ProgramData/choria/var" 16 | - "C:/ProgramData/choria/var/log" 17 | 18 | mcollective::server_config: 19 | classesfile: "C:/ProgramData/PuppetLabs/puppet/cache/state/classes.txt" 20 | logfile: "C:/ProgramData/choria/var/log/choria-mcorpc.log" 21 | plugin.yaml: "C:/ProgramData/choria/etc/generated-facts.yaml" 22 | -------------------------------------------------------------------------------- /manifests/config_file.pp: -------------------------------------------------------------------------------- 1 | # Utility to create mcollective config files 2 | # 3 | # @param settings hash of settings to add via ini_setting 4 | # @param owner File ownership - only used when content is set 5 | # @param group File group ownership - only used when content is set 6 | # @param mode File mode - only used when content is set 7 | # @param content When set manages the entire file 8 | define mcollective::config_file ( 9 | Hash $settings = {}, 10 | Optional[String] $owner = $mcollective::plugin_owner, 11 | Optional[String] $group = $mcollective::plugin_group, 12 | Optional[String] $mode = $mcollective::plugin_mode, 13 | Optional[String] $content = undef, 14 | Enum["present", "absent"] $ensure = "present" 15 | ) { 16 | if $content { 17 | $body = $content 18 | } else { 19 | $body = mcollective::hash2config($settings) 20 | } 21 | file{$name: 22 | owner => $owner, 23 | group => $group, 24 | mode => $mode, 25 | content => $body, 26 | ensure => $ensure 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /templates/refresh_facts.erb: -------------------------------------------------------------------------------- 1 | #!<%= @rubypath %> 2 | 3 | require "optparse" 4 | require "fileutils" 5 | 6 | opt = OptionParser.new 7 | opt.banner = "Store Facts in a YAML file for MCollective" 8 | opt.separator "" 9 | 10 | opt.on("--out FILE", "-o", "Path to facts") do |v| 11 | @outfile = v 12 | end 13 | 14 | opt.on("--pid FILE", "-p", "Path to pidfile") do |v| 15 | @pid = v 16 | end 17 | 18 | opt.parse! 19 | 20 | abort("Please specify a file to write to") unless @outfile 21 | 22 | if @pid 23 | begin 24 | lock = File.open(@pid, File::CREAT | File::EXCL | File::WRONLY) 25 | 26 | at_exit do 27 | begin 28 | lock.close 29 | ensure 30 | File.delete(@pid) 31 | end 32 | end 33 | 34 | lock.write($$) 35 | rescue 36 | abort("Failed to obtain lock for %s using '%s', the refresher may already be running: %s: %s" % [$0, @pid, $!.class, $!.to_s]) 37 | end 38 | end 39 | 40 | require "rubygems" 41 | 42 | if Gem.win_platform? 43 | $: << "C:/Program Files/Puppet Labs/Puppet/facter/lib" 44 | $: << "C:/Program Files/Puppet Labs/Puppet/mcollective/lib" 45 | end 46 | 47 | require "yaml" 48 | require "puppet" 49 | require "facter" 50 | require "tempfile" 51 | 52 | # this was copied from cfactor lib/src/ruby/ruby.cc load_puppet 53 | Puppet.initialize_settings 54 | 55 | unless $LOAD_PATH.include?(Puppet[:libdir]) 56 | $LOAD_PATH.push(Puppet[:libdir]) 57 | end 58 | 59 | Facter.reset 60 | Facter.search_external([Puppet[:pluginfactdest]]) 61 | Puppet.initialize_facts 62 | 63 | file = Tempfile.new("facter_yaml_writer") 64 | # The following conversion back-and-forth to JSON is intended to avoid multiple 65 | # occurence of the same object being output as aliases in the YAML file: 66 | # aliases are not enabled by default by YAML.safe_load because it can be abused 67 | # and have security implications. 68 | file.write(YAML.dump(JSON.load(Facter.to_hash.to_json))) 69 | file.close 70 | 71 | FileUtils.mv(file.path, @outfile) 72 | -------------------------------------------------------------------------------- /lib/facter/mcollective.rb: -------------------------------------------------------------------------------- 1 | Facter.add(:mcollective) do 2 | setcode do 3 | pver = Facter.value(:puppetversion) 4 | aiover = Facter.value(:aio_agent_version) 5 | result = { 6 | "client" => {}, 7 | "server" => {}, 8 | "puppet_major_version" => 0, 9 | "aio_major_version" => 0 10 | } 11 | 12 | result["puppet_major_version"] = pver.split(".").first.to_i if pver 13 | result["aio_major_version"] = aiover.split(".").first.to_i if aiover 14 | 15 | begin 16 | require "mcollective" 17 | 18 | ["client", "server"].each do |config| 19 | if MCollective::Util.windows? 20 | configfile = File.join(MCollective::Util.choria_windows_prefix, "etc", "%s.conf" % config) 21 | else 22 | [ 23 | "/etc/choria/%s.conf", 24 | "/usr/local/etc/choria/%s.conf", 25 | "/etc/puppetlabs/mcollective/%s.cfg", 26 | "/usr/local/etc/mcollective/%s.cfg", 27 | "/etc/mcollective/%s.cfg", 28 | ].each do |path| 29 | configfile = path % config 30 | break if File.exist?(configfile) 31 | end 32 | end 33 | 34 | mconfig = MCollective::Config.instance 35 | 36 | if File.readable?(configfile) 37 | MCollective::PluginManager.clear 38 | mconfig.set_config_defaults(configfile) 39 | mconfig.loadconfig(configfile) 40 | 41 | result[config]["file"] = configfile 42 | result[config]["libdir"] = mconfig.libdir.dup 43 | result[config]["connector"] = mconfig.connector.downcase 44 | result[config]["securityprovider"] = mconfig.securityprovider.downcase 45 | result[config]["collectives"] = mconfig.collectives 46 | result[config]["main_collective"] = mconfig.main_collective 47 | end 48 | end 49 | 50 | result 51 | rescue StandardError, LoadError 52 | result["error"] = "%s: %s" % [$!.class, $!.to_s] 53 | end 54 | 55 | result 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "choria-mcollective", 3 | "version": "0.14.6", 4 | "author": "R.I.Pienaar ", 5 | "license": "Apache-2.0", 6 | "summary": "Configure MCollective as found in the Puppet Agent", 7 | "source": "https://github.com/choria-io/puppet-mcollective", 8 | "project_page": "https://github.com/choria-io/puppet-mcollective", 9 | "issues_url": "https://github.com/choria-io/puppet-mcollective/issues", 10 | "dependencies": [ 11 | { "name": "puppetlabs/stdlib", "version_requirement": ">= 4.24.0 < 10.0.0" }, 12 | { "name": "puppet/systemd", "version_requirement": ">= 5.1.0 < 10.0.0" } 13 | ], 14 | "operatingsystem_support": [ 15 | { 16 | "operatingsystem": "Archlinux" 17 | }, 18 | { 19 | "operatingsystem": "CentOS", 20 | "operatingsystemrelease": [ 21 | "8", 22 | "9" 23 | ] 24 | }, 25 | { 26 | "operatingsystem": "Debian", 27 | "operatingsystemrelease": [ 28 | "12", 29 | "13", 30 | "14" 31 | ] 32 | }, 33 | { 34 | "operatingsystem": "Fedora", 35 | "operatingsystemrelease": [ 36 | "33", 37 | "34", 38 | "35" 39 | ] 40 | }, 41 | { 42 | "operatingsystem": "FreeBSD", 43 | "operatingsystemrelease": [ 44 | "13", 45 | "14" 46 | ] 47 | }, 48 | { 49 | "operatingsystem": "OracleLinux", 50 | "operatingsystemrelease": [ 51 | "8", 52 | "9" 53 | ] 54 | }, 55 | { 56 | "operatingsystem": "RedHat", 57 | "operatingsystemrelease": [ 58 | "8", 59 | "9" 60 | ] 61 | }, 62 | { 63 | "operatingsystem": "RockyLinux", 64 | "operatingsystemrelease": [ 65 | "8", 66 | "9" 67 | ] 68 | }, 69 | { 70 | "operatingsystem": "AlmaLinux", 71 | "operatingsystemrelease": [ 72 | "8", 73 | "9" 74 | ] 75 | }, 76 | { 77 | "operatingsystem": "Ubuntu", 78 | "operatingsystemrelease": [ 79 | "23.10", 80 | "24.04" 81 | ] 82 | }, 83 | { 84 | "operatingsystem": "Windows", 85 | "operatingsystemrelease": [ 86 | "Server 2012", 87 | "Server 2012 R2", 88 | "Server 2016", 89 | "Server 2019", 90 | "Server 2022", 91 | "8", 92 | "10" 93 | ] 94 | } 95 | ], 96 | "requirements": [ 97 | { 98 | "name": "puppet", 99 | "version_requirement": ">= 8.0.0 < 9.0.0" 100 | } 101 | ] 102 | } 103 | -------------------------------------------------------------------------------- /data/common.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | mcollective::collectives: 3 | - "mcollective" 4 | 5 | mcollective::common_config: 6 | securityprovider: "choria" 7 | identity: "%{trusted.certname}" 8 | connector: "nats" 9 | 10 | mcollective::policy_default: "deny" 11 | 12 | mcollective::server_config: 13 | classesfile: "/opt/puppetlabs/puppet/cache/state/classes.txt" 14 | rpcauthorization: 1 15 | rpcauthprovider: "action_policy" 16 | rpcaudit: 1 17 | factsource: "yaml" 18 | plugin.yaml: "/etc/choria/generated-facts.yaml" 19 | logfile: "/var/log/choria-mcorpc.log" 20 | daemonize: 0 21 | 22 | mcollective::client_config: 23 | logger_type: "console" 24 | loglevel: "warn" 25 | connection_timeout: "3" 26 | 27 | mcollective::choria_util_policies: 28 | - action: "allow" 29 | actions: "info" 30 | callers: "*" 31 | facts: "*" 32 | classes: "*" 33 | 34 | mcollective::rpcutil_policies: 35 | - action: "allow" 36 | actions: "ping" 37 | callers: "*" 38 | facts: "*" 39 | classes: "*" 40 | 41 | mcollective::scout_policies: 42 | - action: "allow" 43 | actions: "checks" 44 | callers: "*" 45 | facts: "*" 46 | classes: "*" 47 | 48 | mcollective::plugin_classes: 49 | - mcollective_choria 50 | - mcollective_agent_puppet 51 | - mcollective_agent_service 52 | - mcollective_agent_package 53 | - mcollective_agent_filemgr 54 | - mcollective_util_actionpolicy 55 | - choria 56 | 57 | mcollective::server: true 58 | mcollective::client: false 59 | mcollective::purge: true 60 | mcollective::facts_refresh_type: cron 61 | mcollective::facts_refresh_interval: 10 62 | mcollective::facts_pidfile: "/var/run/puppetlabs/mcollective-facts_refresh.pid" 63 | mcollective::plugin_owner: "root" 64 | mcollective::plugin_group: "root" 65 | mcollective::plugin_mode: "0644" 66 | mcollective::plugin_executable_mode: "0755" 67 | mcollective::bindir: "/usr/bin" 68 | mcollective::libdir: "/opt/puppetlabs/mcollective/plugins" 69 | mcollective::configdir: "/etc/choria" 70 | mcollective::rubypath: "/opt/puppetlabs/puppet/bin/ruby" 71 | mcollective::gem_provider: "puppet_gem" 72 | mcollective::manage_bin_symlinks: true 73 | mcollective::default_rego_policy_source: "puppet:///modules/mcollective/default.rego" 74 | mcollective::plugintypes: 75 | - "agent" 76 | - "aggregate" 77 | - "application" 78 | - "audit" 79 | - "connector" 80 | - "data" 81 | - "discovery" 82 | - "registration" 83 | - "security" 84 | - "util" 85 | - "validator" 86 | - "pluginpackager" 87 | 88 | mcollective::required_directories: 89 | - /opt/puppetlabs/mcollective 90 | 91 | lookup_options: 92 | mcollective::collectives: 93 | merge: "unique" 94 | mcollective::plugin_classes: 95 | merge: "unique" 96 | mcollective::site_policies: 97 | merge: "unique" 98 | mcollective::rpcutil_policies: 99 | merge: "unique" 100 | mcollective::client_config: 101 | merge: 102 | strategy: "deep" 103 | mcollective::server_config: 104 | merge: 105 | strategy: "deep" 106 | mcollective::common_config: 107 | merge: 108 | strategy: "deep" 109 | -------------------------------------------------------------------------------- /manifests/facts.pp: -------------------------------------------------------------------------------- 1 | class mcollective::facts ( 2 | String $libdir = $mcollective::libdir, 3 | String $rubypath = $mcollective::rubypath, 4 | String $configdir = $mcollective::configdir, 5 | String $factspath = $mcollective::factspath, 6 | Optional[Enum['cron', 'systemd']] $refresh_type = $mcollective::facts_refresh_type, 7 | Integer $refresh_interval = $mcollective::facts_refresh_interval, 8 | Optional[String] $owner = $mcollective::plugin_owner, 9 | Optional[String] $group = $mcollective::plugin_group, 10 | Optional[String] $pidfile = $mcollective::facts_pidfile, 11 | Boolean $server = $mcollective::server 12 | ) { 13 | $scriptpath = "${libdir}/mcollective/refresh_facts.rb" 14 | 15 | file{$scriptpath: 16 | owner => $owner, 17 | group => $group, 18 | mode => "0775", 19 | content => template("mcollective/refresh_facts.erb"), 20 | } 21 | 22 | if $refresh_interval > 0 and $server { 23 | if $facts["service_provider"] == "systemd" and $refresh_type == "systemd" { 24 | $cron_ensure = "absent" 25 | $systemd_ensure = "present" 26 | $systemd_active = true 27 | $systemd_enable = true 28 | } else { 29 | $cron_ensure = "present" 30 | $systemd_ensure = "absent" 31 | $systemd_active = false 32 | $systemd_enable = false 33 | } 34 | $cron_offset = "00:${sprintf("%02d", fqdn_rand($refresh_interval, 'facts cronjob'))}" 35 | $cron_minutes = mcollective::crontimes(fqdn_rand($refresh_interval, 'facts cronjob'), $refresh_interval, 60) 36 | $timer_on_calendar = "*:${cron_minutes.join(',')}" 37 | $creates = $factspath 38 | 39 | exec{"mcollective_facts_yaml_refresh": 40 | command => "\"${rubypath}\" \"${scriptpath}\" -o \"${factspath}\"", 41 | creates => $creates, 42 | require => Class["mcollective::config"] 43 | } 44 | } else { 45 | $cron_ensure = "absent" 46 | $systemd_ensure = "absent" 47 | $systemd_active = false 48 | $systemd_enable = false 49 | $cron_offset = "00:00" 50 | $cron_minutes = "0" 51 | $timer_on_calendar = "*:0" 52 | $creates = undef # always run via puppet when opted out of cron option 53 | } 54 | 55 | if $pidfile { 56 | $factspid = "-p '${pidfile}'" 57 | } 58 | 59 | if $facts["os"]["family"] == "windows" { 60 | # on windows task scheduler prevent dupes already so no need to handle the PID here 61 | scheduled_task{"mcollective_facts_yaml_refresh": 62 | ensure => $cron_ensure, 63 | command => $rubypath, 64 | arguments => "'${scriptpath}' -o '${factspath}'", 65 | trigger => { 66 | "schedule" => "daily", 67 | "start_time" => $cron_offset, 68 | "minutes_interval" => $refresh_interval 69 | } 70 | } 71 | } else { 72 | cron{"mcollective_facts_yaml_refresh": 73 | ensure => $cron_ensure, 74 | command => "'${rubypath}' '${scriptpath}' -o '${factspath}' ${factspid} &> /dev/null", 75 | minute => $cron_minutes 76 | } 77 | if $facts["service_provider"] == "systemd" { 78 | systemd::timer { "mcollective-facts-refresh.timer": 79 | ensure => $systemd_ensure, 80 | active => $systemd_active, 81 | enable => $systemd_enable, 82 | timer_content => epp("mcollective/refresh_facts.timer.epp", { 83 | "oncalendar" => $timer_on_calendar, 84 | }), 85 | service_content => epp("mcollective/refresh_facts.service.epp", { 86 | "rubypath" => $rubypath, 87 | "scriptpath" => $scriptpath, 88 | "factspath" => $factspath, 89 | "pidfile" => $pidfile, 90 | }), 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /manifests/init.pp: -------------------------------------------------------------------------------- 1 | # Manage AIO based Marionette Collective 2 | # 3 | # @param plugintypes The list of plugin directories to create under libdir 4 | # @param plugin_classes The list of plugins to install via classes 5 | # @param plugin_classes_exclude A list of plugins not to install 6 | # @param server_config A hash of config items to set in the server.cfg 7 | # @param client_config A hash of config items to set in the client.cfg 8 | # @param common_config A hash of config items to set in both client.cfg and server.cfg 9 | # @param bindir Where to create symlinks for our commands 10 | # @param libdir The directory where plugins will go in 11 | # @param configdir Root directory to config files 12 | # @param facts_refresh_type Kind of fact refresh to run. Choices are cron or systemd (timer) or none. Does not apply to Windows. 13 | # @param facts_refresh_interval Minutes between fact refreshes, set to 0 to disable cron based refreshes 14 | # @param rubypath Path to the ruby executable 15 | # @param collectives A list of collectives the node belongs to 16 | # @param client_collectives A list of collectives the client has access to, defaults to the same as the node 17 | # @param main_collective The main collective to use, last in the list of `$collectives` by default 18 | # @param client_main_collective The main collective to use on the client, `$main_collective` by default 19 | # @param facts_pidfile PID file path for locking fact refresh to a single execution 20 | # @param plugin_owner The default user who will own plugin files 21 | # @param plugin_group The default group who will own plugin files 22 | # @param plugin_mode The default mode plugin files will have 23 | # @param plugin_executable_mode The default mode executable plugin files will have 24 | # @param required_directories Any extra directories that should be created before copying plugins and configuration 25 | # @param policy_default When managing plugin policies this will be the default allow/deny 26 | # @param site_policies Policies to apply to all agents after any module specific policies 27 | # @param rpcutil_policies Policies to apply to the special rpcutil agent 28 | # @param choria_util_policies Policies to apply to the special choria_util agent 29 | # @param scout_policies Policies to apply to the special scout agent 30 | # @param client Install client files on this node 31 | # @param server Install server files on this node 32 | # @param purge When true will remove unmanaged files from the $configdir/plugin.d, $configdir/policies and $libdir 33 | # @param gem_source where to find gems, useful for local gem mirrors 34 | # @param manage_bin_symlinks Enables creating symlinks in the bin dir for the mco command 35 | # @param plugin_file_transfer_type enum to configure global type for file resources in plugins. could be overwritten for every plugin in their defined resource 36 | # @param gem_options Define install_options for gem packages 37 | class mcollective ( 38 | Array[String[1]] $plugintypes, 39 | Array[String[1]] $plugin_classes, 40 | Array[String[1]] $plugin_classes_exclude = [], 41 | Hash $server_config = {}, 42 | Hash $client_config = {}, 43 | Hash $common_config = {}, 44 | Stdlib::Absolutepath $bindir, 45 | Stdlib::Absolutepath $libdir, 46 | Stdlib::Absolutepath $configdir, 47 | Stdlib::Absolutepath $rubypath, 48 | Boolean $manage_bin_symlinks = false, 49 | Optional[Enum["cron", "systemd", "none"]] $facts_refresh_type, 50 | Integer $facts_refresh_interval, 51 | Array[Mcollective::Collective] $collectives, 52 | Array[Mcollective::Collective] $client_collectives = $collectives, 53 | Optional[Mcollective::Collective] $main_collective = undef, 54 | Optional[Mcollective::Collective] $client_main_collective = undef, 55 | Optional[Stdlib::Absolutepath] $facts_pidfile, 56 | Optional[String[1]] $plugin_owner, 57 | Optional[String[1]] $plugin_group, 58 | Optional[Stdlib::Filemode] $plugin_mode, 59 | Optional[Stdlib::Filemode] $plugin_executable_mode, 60 | Array[Stdlib::Absolutepath] $required_directories = [], 61 | Mcollective::Policy_action $policy_default, 62 | Array[Mcollective::Policy] $site_policies = [], 63 | Array[Mcollective::Policy] $rpcutil_policies = [], 64 | Array[Mcollective::Policy] $choria_util_policies = [], 65 | Array[Mcollective::Policy] $scout_policies = [], 66 | Stdlib::Filesource $default_rego_policy_source, 67 | Boolean $client, 68 | Boolean $server, 69 | Boolean $purge, 70 | Optional[String[1]] $gem_source = undef, 71 | String[1] $gem_provider, 72 | Enum['content', 'source'] $plugin_file_transfer_type = 'source', 73 | Optional[Array[String]] $gem_options = [], 74 | ) { 75 | $factspath = "${configdir}/generated-facts.yaml" 76 | 77 | contain mcollective::plugin_dirs 78 | contain mcollective::config 79 | if $facts_refresh_type != "none" { 80 | contain mcollective::facts 81 | } 82 | 83 | contain $plugin_classes - $plugin_classes_exclude 84 | } 85 | -------------------------------------------------------------------------------- /manifests/config.pp: -------------------------------------------------------------------------------- 1 | class mcollective::config { 2 | if $mcollective::manage_bin_symlinks { 3 | file{"${mcollective::bindir}/mco": 4 | ensure => link, 5 | target => "/opt/puppetlabs/puppet/bin/mco", 6 | } 7 | } 8 | 9 | if $mcollective::main_collective { 10 | $main_collective = $mcollective::main_collective 11 | } else { 12 | $main_collective = $mcollective::collectives[-1] 13 | } 14 | 15 | if $mcollective::client_main_collective { 16 | $client_main_collective = $mcollective::client_main_collective 17 | } else { 18 | $client_main_collective = $main_collective 19 | } 20 | 21 | $client_collectives = { 22 | "collectives" => $mcollective::client_collectives.join(","), 23 | "main_collective" => $client_main_collective 24 | } 25 | 26 | $server_collectives = { 27 | "collectives" => $mcollective::collectives.join(","), 28 | "main_collective" => $main_collective 29 | } 30 | 31 | # some config settings are set directly on the main class, they are 32 | # things other classes need to function for example libdir is also 33 | # used by the plugin installer. Specifically these settings should 34 | # never be overridden by settings from the hashes since any difference 35 | # between server/client cfg and what ends up being used by the plugin 36 | # installer will lead to plugins not being found. 37 | $global_config = { 38 | "libdir" => $mcollective::libdir 39 | } 40 | 41 | # These are overrides for the choria shim that we definitely do not want set or have 42 | # to set to specific values for whatever reason 43 | $shim_overrides = { 44 | "rpcaudit" => "0", 45 | "rpcauthorization" => "0", 46 | "collectives" => "mcollective", 47 | "main_collective" => "mcollective", 48 | "daemonize" => "0" 49 | } 50 | 51 | # The order of these are important: 52 | # 53 | # - common config is effectively defaults, overridable by specific server/client settings 54 | # - sub collective setup is derived from the class parameters, but should be overridable by server/client ccofig 55 | # - client_config and server_config has highest priority and overrules everything 56 | # - global config for things like libdir that are properties on the main class. These should always take the main properties. 57 | $server_config = $mcollective::common_config + $server_collectives + $mcollective::server_config + $global_config 58 | $client_config = $mcollective::common_config + $client_collectives + $mcollective::client_config + $global_config 59 | 60 | 61 | $mcollective::required_directories.each |$dir| { 62 | file{$dir: 63 | ensure => "directory", 64 | owner => $mcollective::plugin_owner, 65 | group => $mcollective::plugin_group, 66 | mode => "0775" 67 | } 68 | } 69 | 70 | file{"${mcollective::configdir}/server.cfg": 71 | ensure => absent, 72 | } 73 | 74 | file{"${mcollective::configdir}/client.cfg": 75 | ensure => absent 76 | } 77 | 78 | mcollective::config_file{"${mcollective::configdir}/client.conf": 79 | settings => $client_config, 80 | } 81 | 82 | $temp_shim_config = $mcollective::common_config + $mcollective::server_config + $global_config + $shim_overrides 83 | $shim_config = ["plugin.rpcaudit.logfile", "registerinterval", "registration", "rpcauditprovider"].reduce($temp_shim_config) |$memo, $key| { 84 | $memo.delete($key) 85 | } 86 | 87 | mcollective::config_file{"${mcollective::configdir}/choria-shim.cfg": 88 | settings => $shim_config, 89 | } 90 | 91 | $cu_policy_content = epp("mcollective/policy_file.epp", { 92 | "module" => "choria_util", 93 | "policy_default" => $mcollective::policy_default, 94 | "policies" => $mcollective::choria_util_policies, 95 | "site_policies" => $mcollective::site_policies 96 | }) 97 | 98 | file{"${mcollective::configdir}/policies/choria_util.policy": 99 | owner => $mcollective::plugin_owner, 100 | group => $mcollective::plugin_group, 101 | mode => $mcollective::plugin_mode, 102 | content => $cu_policy_content, 103 | } 104 | 105 | $ru_policy_content = epp("mcollective/policy_file.epp", { 106 | "module" => "rpcutil", 107 | "policy_default" => $mcollective::policy_default, 108 | "policies" => $mcollective::rpcutil_policies, 109 | "site_policies" => $mcollective::site_policies 110 | }) 111 | 112 | file{"${mcollective::configdir}/policies/rpcutil.policy": 113 | owner => $mcollective::plugin_owner, 114 | group => $mcollective::plugin_group, 115 | mode => $mcollective::plugin_mode, 116 | content => $ru_policy_content, 117 | } 118 | 119 | $scout_policy_content = epp("mcollective/policy_file.epp", { 120 | "module" => "scout", 121 | "policy_default" => $mcollective::policy_default, 122 | "policies" => $mcollective::scout_policies, 123 | "site_policies" => $mcollective::site_policies 124 | }) 125 | 126 | file{"${mcollective::configdir}/policies/scout.policy": 127 | owner => $mcollective::plugin_owner, 128 | group => $mcollective::plugin_group, 129 | mode => $mcollective::plugin_mode, 130 | content => $scout_policy_content, 131 | } 132 | 133 | if $mcollective::default_rego_policy_source != "" { 134 | file{"${mcollective::configdir}/policies/rego/default.rego": 135 | owner => $mcollective::plugin_owner, 136 | group => $mcollective::plugin_group, 137 | mode => $mcollective::plugin_mode, 138 | source => $mcollective::default_rego_policy_source, 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /manifests/module_plugin.pp: -------------------------------------------------------------------------------- 1 | define mcollective::module_plugin ( 2 | String $config_name, 3 | Array[String] $client_files = [], 4 | Array[String] $client_directories = [], 5 | Array[String] $server_files = [], 6 | Array[String] $server_directories = [], 7 | Array[String] $common_files = [], 8 | Array[String] $common_directories = [], 9 | Array[String] $executable_files = [], 10 | Boolean $manage_gem_dependencies = true, 11 | Hash $gem_dependencies = {}, 12 | Boolean $manage_package_dependencies = true, 13 | Hash $package_dependencies = {}, 14 | Boolean $manage_class_dependencies = true, 15 | Array[String] $class_dependencies = [], 16 | Mcollective::Policy_action $policy_default = $mcollective::policy_default, 17 | Array[Mcollective::Policy] $policies = [], 18 | Array[Mcollective::Policy] $site_policies = $mcollective::site_policies, 19 | Hash $config = {}, 20 | Hash $client_config = {}, 21 | Hash $server_config = {}, 22 | Boolean $client = $mcollective::client, 23 | Boolean $server = $mcollective::server, 24 | String $libdir = $mcollective::libdir, 25 | String $configdir = $mcollective::configdir, 26 | Optional[String] $owner = $mcollective::plugin_owner, 27 | Optional[String] $group = $mcollective::plugin_group, 28 | Optional[String] $mode = $mcollective::plugin_mode, 29 | Optional[String] $executable_mode = $mcollective::plugin_executable_mode, 30 | Enum["present", "absent"] $ensure = "present", 31 | String $rego_policy_source = "", 32 | Enum['content', 'source'] $file_transfer_type = $mcollective::plugin_file_transfer_type, 33 | Optional[Array[String]] $gem_options = $mcollective::gem_options, 34 | ) { 35 | if $client or $server { 36 | if ($server and $client) { 37 | $merged_conf = $config.deep_merge($client_config).deep_merge($server_config) 38 | $merged_files = $common_files + $server_files + $client_files 39 | $merged_directories = $common_directories + $server_directories + $client_directories 40 | 41 | } elsif ($server) { 42 | $merged_conf = $config.deep_merge($server_config) 43 | $merged_files = $common_files + $server_files 44 | $merged_directories = $common_directories + $server_directories 45 | 46 | } elsif ($client) { 47 | $merged_conf = $config.deep_merge($client_config) 48 | $merged_files = $common_files + $client_files 49 | $merged_directories = $common_directories + $client_directories 50 | } 51 | 52 | if $manage_class_dependencies and !$class_dependencies.empty { 53 | require $class_dependencies 54 | } 55 | 56 | if $manage_package_dependencies { 57 | $package_dependencies.each |$pkg, $version| { 58 | package{$pkg: 59 | ensure => $version, 60 | tag => "mcollective_plugin_${name}_packages" 61 | } 62 | } 63 | } 64 | 65 | if $manage_gem_dependencies { 66 | $gem_dependencies.each |$gem, $version| { 67 | package{$gem: 68 | ensure => $version, 69 | provider => $mcollective::gem_provider, 70 | source => $mcollective::gem_source, 71 | tag => "mcollective_plugin_${name}_packages", 72 | install_options => $gem_options, 73 | } 74 | } 75 | } 76 | 77 | if $name =~ /^mcollective_agent_(.+)/ and $server { 78 | $agent_name = $1 79 | 80 | $policy_content = epp("mcollective/policy_file.epp", { 81 | "module" => $name, 82 | "policy_default" => $policy_default, 83 | "policies" => $policies, 84 | "site_policies" => $site_policies 85 | }) 86 | 87 | file{"${configdir}/policies/${agent_name}.policy": 88 | owner => $owner, 89 | group => $group, 90 | mode => $mode, 91 | content => $policy_content 92 | } 93 | 94 | Package <| tag == "mcollective_plugin_${name}_packages" |> -> File["${configdir}/policies/${agent_name}.policy"] 95 | } 96 | 97 | 98 | if $rego_policy_source != "" { 99 | file{"${configdir}/policies/rego/${agent_name}.rego": 100 | owner => $owner, 101 | group => $group, 102 | mode => $mode, 103 | source => $rego_policy_source 104 | } 105 | } 106 | 107 | unless $merged_conf.empty { 108 | mcollective::config_file { "${configdir}/plugin.d/${config_name}.cfg": 109 | ensure => $ensure, 110 | settings => $merged_conf, 111 | owner => $owner, 112 | group => $group, 113 | mode => $mode 114 | } 115 | } 116 | 117 | $merged_directories.each |$file| { 118 | unless defined(File["${libdir}/mcollective/${file}"]) { 119 | file{"${libdir}/mcollective/${file}": 120 | ensure => $ensure ? {"present" => "directory", "absent" => "absent"}, 121 | owner => $owner, 122 | group => $group, 123 | mode => $mode, 124 | } 125 | 126 | Package <| tag == "mcollective_plugin_${name}_packages" |> -> File["${libdir}/mcollective/${file}"] 127 | } 128 | } 129 | 130 | $merged_files.each |$file| { 131 | if $file =~ /agent\/([^\/]+).rb/ or $file =~ /agent\/([^\/]+)$/ { 132 | $f_tag = "mcollective_agent_${1}_server" 133 | } else { 134 | $f_tag = undef 135 | } 136 | 137 | if $file in $executable_files { 138 | $_mode = $executable_mode 139 | } else { 140 | $_mode = $mode 141 | } 142 | 143 | case $file_transfer_type { 144 | 'source': { 145 | $content = undef 146 | $source = "puppet:///modules/${caller_module_name}/mcollective/${file}" 147 | } 148 | 'content': { 149 | $content = file("${caller_module_name}/mcollective/${file}") 150 | $source = undef 151 | } 152 | } 153 | file{"${libdir}/mcollective/${file}": 154 | ensure => $ensure, 155 | source => $source, 156 | content => $content, 157 | owner => $owner, 158 | group => $group, 159 | mode => $_mode, 160 | tag => $f_tag 161 | } 162 | 163 | Package <| tag == "mcollective_plugin_${name}_packages" |> -> File["${libdir}/mcollective/${file}"] 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | |Date |Issue|Description | 2 | |----------|-----|---------------------------------------------------------------------------------------------------------| 3 | |2024/02/03| |Release 0.14.6 | 4 | |2024/02/07|334 |Fix catalog when systemd is not available | 5 | |2024/02/03| |Release 0.14.5 | 6 | |2023/12/02|331 |Allow disabling facts refresh management | 7 | |2023/11/30|322 |Support Puppet 8 | 8 | |2023/11/28|328 |Allow defining facts refresh as systemd timer | 9 | |2023/09/22|325 |Disable rpcauthorization for shim layer | 10 | |2022/09/18| |Release 0.14.4 | 11 | |2023/09/05| |Support `stdlib` version 9 | 12 | |2022/08/03| |Release 0.14.3 | 13 | |2022/07/07|318 |Call Facter.Value within setcode | 14 | |2022/06/23| |Release 0.14.2 | 15 | |2022/06/09|315 |Support EL9 | 16 | |2022/02/23| |Release 0.14.1 | 17 | |2022/02/23|312 |Sets a default for the gem_options property | 18 | |2022/02/23| |Release 0.14.0 | 19 | |2022/01/04|310 |Add install_options for the gem install | 20 | |2021/10/25|307 |Arch Linux: Switch from Ruby 2.7 to 3 | 21 | |2021/09/30| |Improve module metadata for operating systems and puppet versions | 22 | |2021/09/20| |Release 0.13.4 | 23 | |2021/09/03|303 |Arch Linux: Ensure plugin directory exists | 24 | |2021/09/03|301 |Update rubypath to Ruby 2.7 on Arch Linux | 25 | |2021/08/29| |Release 0.13.3 | 26 | |2021/08/26| |Support latest puppetlabs/stdlib | 27 | |2021/02/29| |Release 0.13.2 | 28 | |2021/03/22|295 |Support latest puppetlabs/stdlib | 29 | |2021/03/18|297 |Fix mcollective fact on windows | 30 | |2021/02/20|291 |Fix logfile path for windows | 31 | |2021/02/03| |Release 0.13.1 | 32 | |2021/01/20|288 |Support extensionless agent executables for `external` agents | 33 | |2021/01/13| |Release 0.13.0 | 34 | |2021/01/07| |Correctly configure file modes on windows | 35 | |2020/12/30|282 |Remove `mcollective::package` class | 36 | |2020/12/28|278 |Relocate configuration to `/etc/choria` | 37 | |2020/12/15|638 |Check choria related paths for configuration | 38 | |2020/12/15|638 |Revert the mcollective server facts | 39 | |2020/12/05| |Remove mcollective::service | 40 | |2020/11/25| |Release 0.12.0 | 41 | |2020/11/23|273 |Initial Puppet 7 support | 42 | |2020/11/05|269 |Improve network utilization by using file() and not source | 43 | |2020/10/22|267 |Remove mcollective server facts | 44 | |2020/10/21|266 |Support FreeBSD | 45 | |2020/10/21|263 |Improve the Puppet datatypes | 46 | |2020/10/21|261 |Improve module containment | 47 | |2020/09/28| |Release 0.11.0 | 48 | |2020/08/24|259 |Add dash to the Mcollective::Collectives pattern | 49 | |2020/07/18| |Release 0.10.5 | 50 | |2020/07/17|254 |Support managing the `scout` agent policies | 51 | |2020/04/19| |Release 0.10.4 | 52 | |2020/04/09|250 |Avoid producing YAML aliases | 53 | |2020/02/11| |Release 0.10.3 | 54 | |2020/01/05|247 |Support copying rego policy files | 55 | |2019/12/02| |Fix ruby path on Windows with Puppet 6 | 56 | |2019/11/26| |Release 0.10.2 | 57 | |2019/10/21| |Update stdlib dependency | 58 | |2019/09/26| |Release 0.10.1 | 59 | |2019/09/26|241 |Support setting some plugin files as executable | 60 | |2019/09/20| |Release 0.10.0 | 61 | |2019/09/18|237 |Retire the AIO Module packager - merged into the choria-mcorpc-support gem | 62 | |2019/09/17|235 |Write `choria_util` policies by default | 63 | |2019/09/16|221 |Use PDK to build modules | 64 | |2019/06/18| |Requires Puppet 6 | 65 | |2019/05/27| |Release 0.9.2 | 66 | |2019/03/13|223 |Avoid repeated mode changes of the fact gatherer script on windows | 67 | |2019/03/04| |Release 0.9.1 | 68 | |2019/01/16|216 |Correctly set permissions for folders on Windows systems | 69 | |2018/12/01| |Release 0.9.0 | 70 | |2018/11/30|212 |On AIO Puppet 6 include the choria class ensuring they use Choria Server by default | 71 | |2018/11/27|206 |Disable `mcollectived` on AIO Puppet 6 | 72 | |2018/11/16|208 |Redirect cron output to /dev/null | 73 | |2018/11/04|203 |Create `mco` symlinks on AIO Puppet 6 | 74 | |2018/11/04|202 |On AIO Puppet 6 skip managing the service even when requested | 75 | |2018/11/03|200 |On AIO Puppet 6 create the standard mcollective directories that exist in 5 | 76 | |2018/09/20| |Release 0.8.1 | 77 | |2018/10/03|197 |Support latest puppetlabs/stdlib | 78 | |2018/09/20| |Release 0.8.0 | 79 | |2018/08/30|193 |Support packaging modules with Puppet installed via gem | 80 | |2018/08/17|191 |Improve FreeBSD support | 81 | |2018/07/30|188 |Add OpenBSD support | 82 | |2018/07/20| |Release 0.7.0 | 83 | |2018/07/11|185 |Support Ubuntu 18.04 | 84 | |2018/06/17|183 |Improve Archlinux support | 85 | |2018/05/21| |Release 0.6.0 | 86 | |2018/05/04|178 |Update location of JSON schema for agent DDLs | 87 | |2018/04/26|176 |Create a `choria-shim.cfg` for the Choria Server Ruby compatibility | 88 | |2018/04/25|174 |Unmanage the Ruby federation broker configuration directory | 89 | |2018/04/20| |Release 0.5.0 | 90 | |2018/04/18|168 |Avoid refreshed of the facts exec when the cron is disabled | 91 | |2018/04/17|166 |Create JSON versions of Agent DDLs | 92 | |2018/03/26| |Release 0.4.1 | 93 | |2018/03/25|163 |Work around for Puppet 5.5.0 breaking changes in facts loading | 94 | |2018/02/25| |Release 0.4.0 | 95 | |2018/02/25|155 |Update `stdlib` dependency | 96 | |2018/02/02|152 |Ensure the `crontimes` function is not called when disabling the cronjob | 97 | |2018/01/04|151 |Remove dependency on the `mcollective_choria` module to avoid cycles in Librarian Puppet | 98 | |2017/12/21| |Release 0.3.0 | 99 | |2017/12/20|148 |Arch Linux support | 100 | |2017/11/15| |Release 0.2.1 | 101 | |2017/10/31|143 |Fix the ability to remove the facts cron from windows | 102 | |2017/10/18| |Release 0.2.0 | 103 | |2017/10/18|140 |Fix gathering mcollective facts from the fact cache builder | 104 | |2017/10/18|138 |Allow plugins to supply additional Puppet files to copy into modules | 105 | |2017/09/21| |Release 0.1.0 | 106 | |2017/09/08|128-134|Support FreeBSD | 107 | |2017/09/08|126 |Improve unixlike behaviour in plugin permissions | 108 | |2017/08/19| |Release 0.0.29 | 109 | |2017/08/18|123 |Ensure a valid `--vendor` is passed when building modules | 110 | |2017/08/02| |Release 0.0.28 | 111 | |2017/06/22|111 |Purge unmanaged config items from the managed config files | 112 | |2017/06/19|113 |Randomize the start time of the facts cron job | 113 | |2017/06/12|110 |Add support for OS X | 114 | |2017/06/01| |Release 0.0.27 | 115 | |2017/06/01|104 |Improve README template for generated modules | 116 | |2017/06/01|103 |Remove deprecation warnings for generated modules on newer Puppet | 117 | |2017/05/28|102 |Remove deprecation warnings on newer Puppet | 118 | |2017/04/27|98 |Support local gem mirrors via the `gem_source` property | 119 | |2017/03/28| |Release 0.0.26 | 120 | |2017/03/24|95 |Ensure the policy file exist before the ini settings are attempted | 121 | |2017/03/21|92 |Add utility to create config files | 122 | |2017/02/13| |Release 0.0.25 | 123 | |2017/02/13|89 |Prevent multiple instances of the fact refresher from running | 124 | |2017/02/11|72 |When mcollective is not available in the RUBYLIB correctly handle the LoadError | 125 | |2017/02/11|80 |Set the `project_page` in the generated modules when packaging a plugin | 126 | |2017/02/11|71 |Enable the `choria` auditing plugin by default | 127 | |2017/02/11| |Release 0.0.24 and move to `choria-io` project | 128 | |2017/02/01|81 |Run the fact generator after the service is up | 129 | |2017/01/29|78 |Convert `-` in module names to `_` | 130 | |2017/01/13| |Release 0.0.23 | 131 | |2017/01/13|74 |Resolve issues with Windows paths in fact and libdir | 132 | |2017/01/03| |Release 0.0.22 | 133 | |2017/01/03|69 |Adjust dependencies so that librarian will install the module | 134 | |2016/11/10| |Release 0.0.21 | 135 | |2016/11/09|67 |Improve handling of agents like the shell one with a invalid plugin layout | 136 | |2016/08/27| |Release 0.0.20 | 137 | |2016/08/27|63 |Deep merge mcollective::common_config | 138 | |2016/08/27|59 |Use a custom fact source - `generated-facts.yaml` - to improve bootstrapping | 139 | |2016/08/27|60 |Configure the classes file according to AIO paths | 140 | |2016/08/13| |Release 0.0.19 | 141 | |2016/08/13|57 |Configure libdirs on windows and rework libdir calculations a bit towards specifically setting libdir | 142 | |2016/08/13|55 |Use the correct lib dirs for facter on windows | 143 | |2016/08/13|54 |Correct typo on hiera data for windows | 144 | |2016/08/13|53 |Correct path to the ruby executable and fix quoting | 145 | |2016/08/13|52 |Correct data types on mcollective::facts for windows support | 146 | |2016/08/11| |Release 0.0.18 | 147 | |2016/08/11|47 |When refreshing facts with cron, do not run facts writer on every Puppet run | 148 | |2016/08/09|43 |Correctly handle temp file renaming in cases where /tmp and /etc do not share a partition (Daniel Sung) | 149 | |2016/08/01| |Release 0.0.17 | 150 | |2016/08/01|41 |Handle cases of both client=false and server=false gracefully in module installer | 151 | |2016/08/01|41 |Uniquely tag agent ruby files to facilitate agent discovery | 152 | |2016/07/31|39 |Install action policies only on nodes with `$server` set | 153 | |2016/07/28|37 |Fix file name for per plugin configs and allow purging old files | 154 | |2016/07/26|35 |Use ripienaar/mcollective-choria instead of specific modules | 155 | |2016/07/12|31 |Improve client sub collective handling | 156 | |2016/07/11|28 |Install the PuppetDB based discovery plugin | 157 | |2016/07/11|25 |Add a `mcollective` fact with various useful information | 158 | |2016/07/11|24 |Move main and audit logs into AIO standard paths | 159 | |2016/07/09|21 |Allow the `rpcutil` agent policies to be managed, set sane defaults | 160 | |2016/07/09|19 |Manages native packages before Gems to allow for compilers to be installed before native gems | 161 | |2016/07/08|17 |Include the NATS.io connector | 162 | |2016/07/07|15 |Support writing factsyaml, include filemgr agent | 163 | |2016/07/06|11 |Support collectives | 164 | |2016/06/30|7 |Support auditlogs | 165 | |2016/06/30|2 |Support Windows | 166 | |2016/06/30|1 |Support actionpolicy | 167 | |2016/06/29|4 |Remove hard coded paths and move them to Hiera | 168 | --------------------------------------------------------------------------------