diff --git a/Puppetfile b/Puppetfile index 284a24af..b4b826c2 100644 --- a/Puppetfile +++ b/Puppetfile @@ -1,183 +1,173 @@ -mod 'profile', - :git => 'https://forge.softwareheritage.org/source/puppet-swh-profile', - :branch => :control_branch, - :default_branch => 'master' - -mod 'role', - :git => 'https://forge.softwareheritage.org/source/puppet-swh-role', - :branch => :control_branch, - :default_branch => 'master' - mod 'dar', :git => 'https://forge.softwareheritage.org/source/puppet-swh-dar', :branch => :control_branch, :default_branch => 'master' mod 'gunicorn', :git => 'https://forge.softwareheritage.org/source/puppet-swh-gunicorn', :branch => :control_branch, :default_branch => 'master' mod 'mediawiki', :git => 'https://forge.softwareheritage.org/source/puppet-swh-mediawiki', :branch => :control_branch, :default_branch => 'master' mod 'postfix', :git => 'https://forge.softwareheritage.org/source/puppet-swh-postfix', :branch => :control_branch, :default_branch => 'master' mod 'uwsgi', :git => 'https://forge.softwareheritage.org/source/puppet-swh-uwsgi', :branch => :control_branch, :default_branch => 'master' mod 'apt', :git => 'https://forge.softwareheritage.org/source/puppet-puppetlabs-apt', :tag => '4.5.1' mod 'archive', :git => 'https://forge.softwareheritage.org/source/puppet-puppet-archive', :tag => 'v2.3.0' mod 'bind', :git => 'https://forge.softwareheritage.org/source/puppet-inkblot-bind', :ref => '7.3.1' mod 'apache', :git => 'https://forge.softwareheritage.org/source/puppet-puppetlabs-apache', :tag => '3.0.0' mod 'ceph', :git => 'https://forge.softwareheritage.org/source/puppet-openstack-ceph', :ref => 'master' mod 'concat', :git => 'https://forge.softwareheritage.org/source/puppet-puppetlabs-concat', :tag => '3.0.0' mod 'cups', :git => 'https://forge.softwareheritage.org/source/puppet-mosen-cups', :ref => 'master' mod 'debconf', :git => 'https://forge.softwareheritage.org/source/puppet-stm-debconf', :ref => 'v2.1.0' mod 'debnet', :git => 'https://forge.softwareheritage.org/source/puppet-trepasi-debnet', :ref => 'v1.5.2' mod 'extlib', :git => 'https://forge.softwareheritage.org/source/puppet-puppet-extlib', :tag => 'v2.0.1' mod 'grafana', :git => 'https://forge.softwareheritage.org/source/puppet-puppet-grafana', :tag => 'v4.2.0' mod 'hitch', :git => 'https://forge.softwareheritage.org/source/puppet-ssm-hitch', :ref => 'feature/additional-config' mod 'icinga2', :git => 'https://forge.softwareheritage.org/source/puppet-icinga-icinga2', :tag => 'v1.3.5' mod 'icingaweb2', :git => 'https://forge.softwareheritage.org/source/puppet-icinga-icingaweb2', :tag => 'v2.1.0' mod 'inifile', :git => 'https://forge.softwareheritage.org/source/puppet-puppetlabs-inifile', :ref => '2.2.0' mod 'java', :git => 'https://forge.softwareheritage.org/source/puppet-puppetlabs-java', :tag => '2.4.0' mod 'kafka', :git => 'https://forge.softwareheritage.org/source/puppet-puppet-kafka', :ref => 'v5.0.0' mod 'locales', :git => 'https://forge.softwareheritage.org/source/puppet-saz-locales', :ref => 'v2.5.0' mod 'munin', :git => 'https://forge.softwareheritage.org/source/puppet-ssm-munin', :ref => '0.1.0' mod 'mysql', :git => 'https://forge.softwareheritage.org/source/puppet-puppetlabs-mysql', :ref => '5.3.0' mod 'nginx', :git => 'https://forge.softwareheritage.org/source/puppet-puppet-nginx', :ref => 'v0.11.0' mod 'ntp', :git => 'https://forge.softwareheritage.org/source/puppet-puppetlabs-ntp', :ref => '6.4.1' mod 'php', :git => 'https://forge.softwareheritage.org/source/puppet-puppet-php', :ref => 'v5.3.0' mod 'postgresql', :git => 'https://forge.softwareheritage.org/source/puppet-puppetlabs-postgresql', :ref => '5.3.0' mod 'puppet', :git => 'https://forge.softwareheritage.org/source/puppet-theforeman-puppet', :tag => '8.2.0' mod 'puppetdb', :git => 'https://forge.softwareheritage.org/source/puppet-puppetlabs-puppetdb', :ref => '6.0.2' mod 'memcached', :git => 'https://forge.softwareheritage.org/source/puppet-saz-memcached', :ref => 'v3.1.0' mod 'resolv_conf', :git => 'https://forge.softwareheritage.org/source/puppet-saz-resolv_conf', :ref => 'v3.3.0' mod 'ssh', :git => 'https://forge.softwareheritage.org/source/puppet-saz-ssh', :ref => 'v3.0.1' mod 'stdlib', :git => 'https://forge.softwareheritage.org/source/puppet-puppetlabs-stdlib', :ref => '4.25.0' mod 'sudo', :git => 'https://forge.softwareheritage.org/source/puppet-saz-sudo', :ref => 'v5.0.0' mod 'systemd', :git => 'https://forge.softwareheritage.org/source/puppet-camptocamp-systemd', :ref => '1.1.1' mod 'timezone', :git => 'https://forge.softwareheritage.org/source/puppet-saz-timezone', :ref => 'v4.1.1' mod 'unattended_upgrades', :git => 'https://forge.softwareheritage.org/source/puppet-puppet-unattended_upgrades', :ref => 'v3.1.0' mod 'varnish', :git => 'https://forge.softwareheritage.org/source/puppet-claranet-varnish', :ref => '5.0.0' mod 'vcsrepo', :git => 'https://forge.softwareheritage.org/source/puppet-puppetlabs-vcsrepo', :ref => '2.3.0' mod 'zookeeper', :git => 'https://forge.softwareheritage.org/source/puppet-deric-zookeeper', :ref => 'v0.7.7' diff --git a/environment.conf b/environment.conf new file mode 100644 index 00000000..0cbb74fc --- /dev/null +++ b/environment.conf @@ -0,0 +1 @@ +modulepath = site-modules:modules diff --git a/site-modules/profile/AUTHORS b/site-modules/profile/AUTHORS new file mode 100644 index 00000000..2d0a34af --- /dev/null +++ b/site-modules/profile/AUTHORS @@ -0,0 +1,3 @@ +Copyright (C) 2015 The Software Heritage developers + +See http://www.softwareheritage.org/ for more information. diff --git a/site-modules/profile/Gemfile b/site-modules/profile/Gemfile new file mode 100644 index 00000000..7bd34cda --- /dev/null +++ b/site-modules/profile/Gemfile @@ -0,0 +1,7 @@ +source 'https://rubygems.org' + +puppetversion = ENV.key?('PUPPET_VERSION') ? "= #{ENV['PUPPET_VERSION']}" : ['>= 3.3'] +gem 'puppet', puppetversion +gem 'puppetlabs_spec_helper', '>= 0.1.0' +gem 'puppet-lint', '>= 0.3.2' +gem 'facter', '>= 1.7.0' diff --git a/site-modules/profile/LICENSE b/site-modules/profile/LICENSE new file mode 100644 index 00000000..37ec93a1 --- /dev/null +++ b/site-modules/profile/LICENSE @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/site-modules/profile/README.md b/site-modules/profile/README.md new file mode 100644 index 00000000..3b574f2b --- /dev/null +++ b/site-modules/profile/README.md @@ -0,0 +1,79 @@ +# profile + +#### Table of Contents + +1. [Overview](#overview) +2. [Module Description - What the module does and why it is useful](#module-description) +3. [Setup - The basics of getting started with profile](#setup) + * [What profile affects](#what-profile-affects) + * [Setup requirements](#setup-requirements) + * [Beginning with profile](#beginning-with-profile) +4. [Usage - Configuration options and additional functionality](#usage) +5. [Reference - An under-the-hood peek at what the module is doing and how](#reference) +5. [Limitations - OS compatibility, etc.](#limitations) +6. [Development - Guide for contributing to the module](#development) + +## Overview + +A one-maybe-two sentence summary of what the module does/what problem it solves. +This is your 30 second elevator pitch for your module. Consider including +OS/Puppet version it works with. + +## Module Description + +If applicable, this section should have a brief description of the technology +the module integrates with and what that integration enables. This section +should answer the questions: "What does this module *do*?" and "Why would I use +it?" + +If your module has a range of functionality (installation, configuration, +management, etc.) this is the time to mention it. + +## Setup + +### What profile affects + +* A list of files, packages, services, or operations that the module will alter, + impact, or execute on the system it's installed on. +* This is a great place to stick any warnings. +* Can be in list or paragraph form. + +### Setup Requirements **OPTIONAL** + +If your module requires anything extra before setting up (pluginsync enabled, +etc.), mention it here. + +### Beginning with profile + +The very basic steps needed for a user to get the module up and running. + +If your most recent release breaks compatibility or requires particular steps +for upgrading, you may wish to include an additional section here: Upgrading +(For an example, see http://forge.puppetlabs.com/puppetlabs/firewall). + +## Usage + +Put the classes, types, and resources for customizing, configuring, and doing +the fancy stuff with your module here. + +## Reference + +Here, list the classes, types, providers, facts, etc contained in your module. +This section should include all of the under-the-hood workings of your module so +people know what the module is touching on their system but don't need to mess +with things. (We are working on automating this section!) + +## Limitations + +This is where you list OS compatibility, version compatibility, etc. + +## Development + +Since your module is awesome, other users will want to play with it. Let them +know what the ground rules for contributing are. + +## Release Notes/Contributors/Etc **Optional** + +If you aren't using changelog, put your release notes here (though you should +consider using changelog). You may also add any additional sections you feel are +necessary or important to include here. Please use the `## ` header. diff --git a/site-modules/profile/Rakefile b/site-modules/profile/Rakefile new file mode 100644 index 00000000..841f2cc5 --- /dev/null +++ b/site-modules/profile/Rakefile @@ -0,0 +1,22 @@ +require 'rubygems' +require 'puppetlabs_spec_helper/rake_tasks' +require 'puppet-lint/tasks/puppet-lint' +PuppetSyntax.future_parser = true +PuppetLint.configuration.send('disable_80chars') +PuppetLint.configuration.send('disable_autoloader_layout') +PuppetLint.configuration.send('disable_variable_scope') +PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"] + +desc "Validate manifests, templates, and ruby files" +task :validate do + parser_flag = Puppet.version.start_with?('3.') ? '--parser=future' : '' + Dir['manifests/**/*.pp'].each do |manifest| + sh "puppet parser validate #{parser_flag} --noop #{manifest}" + end + Dir['spec/**/*.rb','lib/**/*.rb'].each do |ruby_file| + sh "ruby -c #{ruby_file}" unless ruby_file =~ /spec\/fixtures/ + end + Dir['templates/**/*.erb'].each do |template| + sh "erb -P -x -T '-' #{template} | ruby -c" + end +end diff --git a/site-modules/profile/files/desktop/printers/MFP_auth_filter b/site-modules/profile/files/desktop/printers/MFP_auth_filter new file mode 100755 index 00000000..8e6dbbe2 --- /dev/null +++ b/site-modules/profile/files/desktop/printers/MFP_auth_filter @@ -0,0 +1,488 @@ +#!/usr/bin/perl -w + +# 7.22 (01 November 2013) + +use warnings; +my %IQsOQdemWnRpKqgX9ckOY7a; +my %IQddZwV6KPGAiuqlymAjaf9; +my $CgQgehjU2fkeP3IuU_SluaS = 0; +my $IQlTd0tjxipX5EM8bpksT9f = 0; +my $RgdbYnWd0mYfstEI94Kmas1 = -1; +my $NgLsAFr0eWBtUkx_ph10zLd = -1; +my $OwEORWd_diPRRfMjclgacYG = 0; +my $Pg7kuusKmFTpUKGI83WDyI4 = 0; +my $RgH6C062x1Obd2hS5mfo1kc = 0; +my %VAo9NQ_6OV7q4PDBhbsVUIW = ( +"Auto" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 9 /MediaType null >> setpagedevice +userdict /TSBMediaType 0 put +%%EndFeature +} stopped cleartomark', +"Thin" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 9 /MediaType (Thin) >> setpagedevice +userdict /TSBMediaType 11 put +%%EndFeature +} stopped cleartomark', +"UpperCassette" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 0 /MediaType null >> setpagedevice +userdict /TSBMediaType 0 put +%%EndFeature +} stopped cleartomark', +"LowerCassette" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 1 /MediaType null >> setpagedevice +userdict /TSBMediaType 0 put +%%EndFeature +} stopped cleartomark', +"LCF" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 4 /MediaType null >> setpagedevice +userdict /TSBMediaType 0 put +%%EndFeature +} stopped cleartomark', +"PedestalUpperCassette" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 4 /MediaType null >> setpagedevice +userdict /TSBMediaType 0 put +%%EndFeature +} stopped cleartomark', +"PedestalLowerCassette" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 5 /MediaType null >> setpagedevice +userdict /TSBMediaType 0 put +%%EndFeature +} stopped cleartomark', +"SheetFeedBypass" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed true +/MediaPosition 3 /MediaType null >> setpagedevice +userdict /TSBMediaType 0 put +%%EndFeature +} stopped cleartomark', +"TandemLCF" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 4 /MediaType null >> setpagedevice +userdict /TSBMediaType 0 put +%%EndFeature +} stopped cleartomark', +"ExternalLCF" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 6 /MediaType null >> setpagedevice +userdict /TSBMediaType 0 put +%%EndFeature +} stopped cleartomark', +"Plain" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 9 /MediaType (Plain) >> setpagedevice +userdict /TSBMediaType 0 put +<> setpagedevice +%%EndFeature +} stopped cleartomark', +"PlainA" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 9 /MediaType (Plain) >> setpagedevice +userdict /TSBMediaType 0 put +<> setpagedevice +%%EndFeature +} stopped cleartomark', +"Plain1" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 9 /MediaType (Plain1) >> setpagedevice +userdict /TSBMediaType 0 put +<> setpagedevice +%%EndFeature +} stopped cleartomark', +"Plain2" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 9 /MediaType (Plain2) >> setpagedevice +userdict /TSBMediaType 0 put +<> setpagedevice +%%EndFeature +} stopped cleartomark', +"Thick1" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 9 /MediaType (Thick 1) >> setpagedevice +userdict /TSBMediaType 1 put +<> setpagedevice +%%EndFeature +} stopped cleartomark', +"Thick1back" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 9 /MediaType (Thick 1b) >> setpagedevice +userdict /TSBMediaType 1 put +<> setpagedevice +%%EndFeature +} stopped cleartomark', +"Thick2" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 9 /MediaType (Thick 2) >> setpagedevice +userdict /TSBMediaType 2 put +<> setpagedevice +%%EndFeature +} stopped cleartomark', +"Thick2back" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 9 /MediaType (Thick 2b) >> setpagedevice +userdict /TSBMediaType 3 put +<> setpagedevice +%%EndFeature +} stopped cleartomark', +"Thick3" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 9 /MediaType (Thick 3) >> setpagedevice +userdict /TSBMediaType 4 put +<> setpagedevice +%%EndFeature +} stopped cleartomark', +"Thick3back" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 9 /MediaType (Thick 3b) >> setpagedevice +userdict /TSBMediaType 4 put +<> setpagedevice +%%EndFeature +} stopped cleartomark', +"Thick4" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 9 /MediaType (Thick 4) >> setpagedevice +userdict /TSBMediaType 4 put +<> setpagedevice +%%EndFeature +} stopped cleartomark', +"Thick4back" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 9 /MediaType (Thick 4b) >> setpagedevice +userdict /TSBMediaType 4 put +<> setpagedevice +%%EndFeature +} stopped cleartomark', +"Transparency" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed true +/MediaPosition 9 /MediaType (Transparency) >> setpagedevice +userdict /TSBMediaType 5 put +<> setpagedevice +%%EndFeature +} stopped cleartomark', +"Recycled" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 9 /MediaType (Recycled) >> setpagedevice +userdict /TSBMediaType 6 put +<> setpagedevice +%%EndFeature +} stopped cleartomark', +"Special1" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 9 /MediaType (Waterproof 1) >> setpagedevice +userdict /TSBMediaType 7 put +<< /OutputPosition 3 >> setpagedevice +<> setpagedevice +%%EndFeature +} stopped cleartomark', +"Special1back" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 9 /MediaType (Waterproof 1b) >> setpagedevice +userdict /TSBMediaType 8 put +<< /OutputPosition 3 >> setpagedevice +<> setpagedevice +%%EndFeature +} stopped cleartomark', +"Special2" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 9 /MediaType (Waterproof 2) >> setpagedevice +userdict /TSBMediaType 9 put +<< /OutputPosition 3 >> setpagedevice +<> setpagedevice +%%EndFeature +} stopped cleartomark', +"Special2back" => ' +[{ +%%BeginFeature: *paperSource ok +<< /DeferredMediaSelection true /ManualFeed false +/MediaPosition 9 /MediaType (Waterproof 2b) >> setpagedevice +userdict /TSBMediaType 10 put +<< /OutputPosition 3 >> setpagedevice +<> setpagedevice +%%EndFeature +} stopped cleartomark' +); +my $FglgkIk3FkJuea4yg45GKKS = ""; +my $Rgig05yAdP87v5aUne4pvMp = 0; +my $KwrHRUAQOB_9zEJmYK7BgDJ; +my $Zw3xzK1N60_42I7h9ki6syC = "CUPS User"; +my $VAx0IN05N6mheBLY6acC3Q_ = "CUPS Document"; +$FglgkIk3FkJuea4yg45GKKS = `domainname`; +chomp $FglgkIk3FkJuea4yg45GKKS; +if (length( $FglgkIk3FkJuea4yg45GKKS) == 0) +{$KwrHRUAQOB_9zEJmYK7BgDJ = "False"; +}else +{$KwrHRUAQOB_9zEJmYK7BgDJ = "True"; +}my %XAZt5_uRiv_LxHCSXzfN9Fc = ( +"True" => ' +[{ +%%BeginFeature: *UserAuthentication True +<> setpagedevice +<> setpagedevice +%%EndFeature +} stopped cleartomark +', +"False" => ' +[{ +%%BeginFeature: *UserAuthentication False +<> setpagedevice +<> setpagedevice +%%EndFeature +} stopped cleartomark +' +); +my $ZANthMYeXyYLcEp_9ouCR1R = ' [{ +%%BeginFeature: *Duplex NoDuplex +<> setpagedevice +%%EndFeature +} stopped cleartomark'; +my @Fgq5sA_PwVW_ShNX38akDvi = split(/(?)) +{if ($MAYuL63LQjlLfvOn4nR_IaT =~ /<<\/TSBPrivate \(DSSC PRINT USERLOGIN=(.*)\) >> setpagedevice/ ) +{$MAYuL63LQjlLfvOn4nR_IaT = "<> setpagedevice\n"; +}if ($MAYuL63LQjlLfvOn4nR_IaT =~ /<<\/TSBPrivate \(DSSC JOB NAME=(.*)\) >> setpagedevice/ ) +{$MAYuL63LQjlLfvOn4nR_IaT = "<> setpagedevice\n"; +}if ($MAYuL63LQjlLfvOn4nR_IaT =~ /^\%\%BeginSetup/ && $PwsEc1XImx03gTEUZBUbza2 != 1) +{print $MAYuL63LQjlLfvOn4nR_IaT; +my $ZQuIMYrqEQh0apZoii8gG06 = 1; +my $MAtcZ_Rp_Fl2wS9mC_KrKlO = $IQsOQdemWnRpKqgX9ckOY7a{"com.apple.print.PrintSettings.PMLayoutRows..n."}; +my $MgasYOuyeXOQox_TZJ8HKLy = $IQsOQdemWnRpKqgX9ckOY7a{"com.apple.print.PrintSettings.PMLayoutColumns..n."}; +if (defined($MAtcZ_Rp_Fl2wS9mC_KrKlO) and defined($MgasYOuyeXOQox_TZJ8HKLy)) +{ $ZQuIMYrqEQh0apZoii8gG06 = $MAtcZ_Rp_Fl2wS9mC_KrKlO * $MgasYOuyeXOQox_TZJ8HKLy }$MAYuL63LQjlLfvOn4nR_IaT = "<> setpagedevice\n"; +$PwsEc1XImx03gTEUZBUbza2 = 1; +}if ( $MAYuL63LQjlLfvOn4nR_IaT =~ /\%\%Page:\s*(\d+)\s*/) +{$IQlTd0tjxipX5EM8bpksT9f = $1; +if ($IQlTd0tjxipX5EM8bpksT9f == 1 ) +{if(!defined $IQddZwV6KPGAiuqlymAjaf9{"InputSlot"}) +{$IQddZwV6KPGAiuqlymAjaf9{"InputSlot"} = "Auto"; +}if ( $IQddZwV6KPGAiuqlymAjaf9{"UseFrontCover"} eq "True" ) +{$RgdbYnWd0mYfstEI94Kmas1 = LAXUX6rBHE9_kThT1ViJumr(); +}if( $IQddZwV6KPGAiuqlymAjaf9{"UseBackCover"} eq "True" ) +{$NgLsAFr0eWBtUkx_ph10zLd = NgBqXkrPQke_x_sDyDPuQ1M(); +}}if ( $IQlTd0tjxipX5EM8bpksT9f == $RgdbYnWd0mYfstEI94Kmas1 ) +{if ($IQddZwV6KPGAiuqlymAjaf9{"Duplex"} ne "None") +{OQg31OtLYDVoheJXme4GMcl(); +}Yg_pv8thjFMU91046_04dKY(); +}if ($IQlTd0tjxipX5EM8bpksT9f == $NgLsAFr0eWBtUkx_ph10zLd) +{if ( $IQddZwV6KPGAiuqlymAjaf9{"Duplex"} ne "None" ) +{if ( $IQddZwV6KPGAiuqlymAjaf9{"BackCoverPrintStyle"} eq "Print1" ) +{print ($ZANthMYeXyYLcEp_9ouCR1R); +}}KAVqkrt4s_47MR1s3oVhOM3(); +}}if ( ($IQlTd0tjxipX5EM8bpksT9f == 1) && ($RgH6C062x1Obd2hS5mfo1kc != 1)) +{if ( $IQddZwV6KPGAiuqlymAjaf9{'UseFrontCover'} ne "True" ) +{if ($MAYuL63LQjlLfvOn4nR_IaT =~ /\%\%BeginFeature:/) +{if ( $IQddZwV6KPGAiuqlymAjaf9{'UseBackCover'} eq "True" ) +{$CgQgehjU2fkeP3IuU_SluaS--; +$NgLsAFr0eWBtUkx_ph10zLd = NgBqXkrPQke_x_sDyDPuQ1M(); +$CgQgehjU2fkeP3IuU_SluaS++; +$NgLsAFr0eWBtUkx_ph10zLd++; +$RgH6C062x1Obd2hS5mfo1kc = 1; +}}}}if ( $IQlTd0tjxipX5EM8bpksT9f != 0 ) +{if ( $IQddZwV6KPGAiuqlymAjaf9{'UseFrontCover'} eq "True" ) +{if ($MAYuL63LQjlLfvOn4nR_IaT =~ /\%\%BeginFeature:/) +{$Pg7kuusKmFTpUKGI83WDyI4 = 1; +}if ($MAYuL63LQjlLfvOn4nR_IaT =~ /\%\%EndFeature/) +{$Pg7kuusKmFTpUKGI83WDyI4 = 0; +$MAYuL63LQjlLfvOn4nR_IaT = ""; +}if ($Pg7kuusKmFTpUKGI83WDyI4 == 1) +{$MAYuL63LQjlLfvOn4nR_IaT = ""; +}}}if ( ($MAYuL63LQjlLfvOn4nR_IaT =~ /\%\%EOF/) && ($NgLsAFr0eWBtUkx_ph10zLd == $CgQgehjU2fkeP3IuU_SluaS + 1)) +{if ( $IQddZwV6KPGAiuqlymAjaf9{"Duplex"} ne "None" ) +{print ($ZANthMYeXyYLcEp_9ouCR1R); +}$OwEORWd_diPRRfMjclgacYG = 1; +KAVqkrt4s_47MR1s3oVhOM3(); +Cw4Mkys2_8v2e9cwu4aKEjQ(); +}if ($IQlTd0tjxipX5EM8bpksT9f == 0 ) +{if ($MAYuL63LQjlLfvOn4nR_IaT =~ /\%\%BeginFeature:\s*\*(\S*)\s*(\S*)/) +{my $VAlLZextcELhv1X2BM7_pvq = $1; +my $Pgld7xc58fAiA5CvSN3mXQC = $2; +$IQddZwV6KPGAiuqlymAjaf9{$VAlLZextcELhv1X2BM7_pvq} = $Pgld7xc58fAiA5CvSN3mXQC; +}if ( $MAYuL63LQjlLfvOn4nR_IaT =~ /\/Pages\s*(\d+).*/ ) +{$CgQgehjU2fkeP3IuU_SluaS = $1; +}}if ($MAYuL63LQjlLfvOn4nR_IaT =~ /\%\%BeginFeature:\s*\*DeptCode/) +{$Rgig05yAdP87v5aUne4pvMp = 1; +}if ( ($Rgig05yAdP87v5aUne4pvMp == 1) && ( $MAYuL63LQjlLfvOn4nR_IaT =~ /}\s*stopped\s*cleartomark/ ) ) +{my $BgZ5P_MZ2FTwIdx_khSFhge = $XAZt5_uRiv_LxHCSXzfN9Fc{"$KwrHRUAQOB_9zEJmYK7BgDJ"}; +$MAYuL63LQjlLfvOn4nR_IaT .= "\n$BgZ5P_MZ2FTwIdx_khSFhge\n"; +$Rgig05yAdP87v5aUne4pvMp = 0; +}print( $MAYuL63LQjlLfvOn4nR_IaT ); +}if ($IQddZwV6KPGAiuqlymAjaf9{'UseBackCover'} eq "True") +{if (($OwEORWd_diPRRfMjclgacYG != 1) && ($IQddZwV6KPGAiuqlymAjaf9{'BackCoverPrintStyle'} eq "NoPrint")) +{KAVqkrt4s_47MR1s3oVhOM3 (); +Cw4Mkys2_8v2e9cwu4aKEjQ (); +print "%%EOF"; +}}sub Yg_pv8thjFMU91046_04dKY +{my $Vg7pxS85Je2d3dKRIeMY0qk = $IQddZwV6KPGAiuqlymAjaf9{"InputSlot"}; +my $SAv1MaaCf_HfvaAP2AbswHD = $VAo9NQ_6OV7q4PDBhbsVUIW{"$Vg7pxS85Je2d3dKRIeMY0qk"}; +print ("\n$SAv1MaaCf_HfvaAP2AbswHD\n"); +}sub NgBqXkrPQke_x_sDyDPuQ1M +{my $VQDs1UaDsMh_Ql0CnAehnva = $CgQgehjU2fkeP3IuU_SluaS; +if ( $IQddZwV6KPGAiuqlymAjaf9{"BackCoverPrintStyle"} eq "NoPrint" ) +{$VQDs1UaDsMh_Ql0CnAehnva = $CgQgehjU2fkeP3IuU_SluaS + 1; +}elsif ( $IQddZwV6KPGAiuqlymAjaf9{"BackCoverPrintStyle"} eq "Print" ) +{if ( $IQddZwV6KPGAiuqlymAjaf9{"Duplex"} eq "None" ) +{if ($CgQgehjU2fkeP3IuU_SluaS > 1) +{$VQDs1UaDsMh_Ql0CnAehnva = $CgQgehjU2fkeP3IuU_SluaS; +}else +{$VQDs1UaDsMh_Ql0CnAehnva = -1; +}}else +{if ( $CgQgehjU2fkeP3IuU_SluaS == 2 ) +{if ( ($IQddZwV6KPGAiuqlymAjaf9{'UseFrontCover'} eq "True") && +($IQddZwV6KPGAiuqlymAjaf9{'FrontCoverPrintStyle'} eq "Print1")) +{$VQDs1UaDsMh_Ql0CnAehnva = $CgQgehjU2fkeP3IuU_SluaS; +}}elsif ($CgQgehjU2fkeP3IuU_SluaS > 2) +{if ( ($IQddZwV6KPGAiuqlymAjaf9{'UseFrontCover'} eq "True") && +($IQddZwV6KPGAiuqlymAjaf9{'FrontCoverPrintStyle'} eq "Print1")) +{if ( ($CgQgehjU2fkeP3IuU_SluaS % 2) != 0 ) +{$VQDs1UaDsMh_Ql0CnAehnva = $CgQgehjU2fkeP3IuU_SluaS - 1; +}else +{$VQDs1UaDsMh_Ql0CnAehnva = $CgQgehjU2fkeP3IuU_SluaS; +}}else +{if ( ($CgQgehjU2fkeP3IuU_SluaS % 2) != 0 ) +{$VQDs1UaDsMh_Ql0CnAehnva = $CgQgehjU2fkeP3IuU_SluaS; +}else +{$VQDs1UaDsMh_Ql0CnAehnva = $CgQgehjU2fkeP3IuU_SluaS - 1; +}}}else +{$VQDs1UaDsMh_Ql0CnAehnva = -1; +}}}elsif ( $IQddZwV6KPGAiuqlymAjaf9{"BackCoverPrintStyle"} eq "Print1" ) +{if ($CgQgehjU2fkeP3IuU_SluaS > 1) +{$VQDs1UaDsMh_Ql0CnAehnva = $CgQgehjU2fkeP3IuU_SluaS; +}else +{$VQDs1UaDsMh_Ql0CnAehnva = -1; +}}return $VQDs1UaDsMh_Ql0CnAehnva; +}sub KAVqkrt4s_47MR1s3oVhOM3 +{my $VAbI7UXk4XwwdfFVS_YarYc = $IQddZwV6KPGAiuqlymAjaf9{"BackCoverSource"}; +my $SAv1MaaCf_HfvaAP2AbswHD = $VAo9NQ_6OV7q4PDBhbsVUIW{"$VAbI7UXk4XwwdfFVS_YarYc"}; +print ("\n$SAv1MaaCf_HfvaAP2AbswHD\n"); +}sub LAXUX6rBHE9_kThT1ViJumr +{my $YQYou_rUvKNwAebrhpy3ONu = $IQddZwV6KPGAiuqlymAjaf9{"FrontCoverSource"}; +my $SAv1MaaCf_HfvaAP2AbswHD = $VAo9NQ_6OV7q4PDBhbsVUIW{"$YQYou_rUvKNwAebrhpy3ONu"}; +print ("\n$SAv1MaaCf_HfvaAP2AbswHD\n"); +if ( $IQddZwV6KPGAiuqlymAjaf9{"FrontCoverPrintStyle"} eq "NoPrint" ) +{if ( $IQddZwV6KPGAiuqlymAjaf9{"Duplex"} ne "None" ) +{print ($ZANthMYeXyYLcEp_9ouCR1R); +}Cw4Mkys2_8v2e9cwu4aKEjQ(); +return 1; +}elsif ( $IQddZwV6KPGAiuqlymAjaf9{"FrontCoverPrintStyle"} eq "Print" ) +{if ( $IQddZwV6KPGAiuqlymAjaf9{"Duplex"} eq "None" ) +{return 2; +}else +{return 3; +}}elsif ( $IQddZwV6KPGAiuqlymAjaf9{"FrontCoverPrintStyle"} eq "Print1" ) +{if ( $IQddZwV6KPGAiuqlymAjaf9{"Duplex"} ne "None" ) +{print ($ZANthMYeXyYLcEp_9ouCR1R); +}return 2; +}else +{}}sub OQg31OtLYDVoheJXme4GMcl +{if ( $IQddZwV6KPGAiuqlymAjaf9{"Duplex"} eq "DuplexNoTumble" ) +{print ' +[{ +%%BeginFeature: *Duplex setting +<< /Duplex true /Tumble false >> setpagedevice +%%EndFeature +} stopped cleartomark'; +}elsif ( $IQddZwV6KPGAiuqlymAjaf9{"Duplex"} eq "DuplexTumble" ) +{print ' +[{ +%%BeginFeature: *Duplex setting +<< /Duplex true /Tumble true >> setpagedevice +%%EndFeature +} stopped cleartomark'; +}else +{print ' +[{ +%%BeginFeature: *Duplex setting +<< /Duplex false /Tumble false >> setpagedevice +%%EndFeature +} stopped cleartomark'; +}}sub PQpforKzO6hVgyBsEnu2Gjd +{print( "Print Feature Hash\n" ); +Yw0hll42BnESxxL94xo50oO(); +}sub Yw0hll42BnESxxL94xo50oO +{foreach my $JwW2OO_Egq8Fkrsb5GUVeY0 (sort(keys(%IQddZwV6KPGAiuqlymAjaf9))) +{print "$JwW2OO_Egq8Fkrsb5GUVeY0: $IQddZwV6KPGAiuqlymAjaf9{$JwW2OO_Egq8Fkrsb5GUVeY0}\n"; +}}sub Cw4Mkys2_8v2e9cwu4aKEjQ +{print( "\nshowpage\n" ); +}sub IA6zNEzpp42_KaxiOHzdlJk +{my $SgsLFTthhmv_sZ1qGrsN3iV = $_[0]; +if ($SgsLFTthhmv_sZ1qGrsN3iV =~ m/^\((.*)\)$/) +{$SgsLFTthhmv_sZ1qGrsN3iV = $1; +}foreach my $PwUajytA_SVkp_zcip7OZka ($_[0] =~ m/(?<=\\)([0-3][0-7][0-7])/g) +{$SgsLFTthhmv_sZ1qGrsN3iV =~ s/\\$PwUajytA_SVkp_zcip7OZka/chr oct $PwUajytA_SVkp_zcip7OZka/ge; +}$SgsLFTthhmv_sZ1qGrsN3iV =~ s/\\(?>![\(\)])/\\\\/g; +$SgsLFTthhmv_sZ1qGrsN3iV =~ s/(? +# Retrieved from https://github.com/raphaelm/monitoring/blob/master/mail/check_mail_twoway +# Published under the MIT license + +class BooleanContext(nagiosplugin.Context): + """This context only cares about boolean values. + You can specify using the ``critical``-parameter whether + a False result should cause a warning or a critical error. + """ + + def __init__(self, name, critical=True, + fmt_metric='{name} is {value}', + result_cls=nagiosplugin.result.Result): + self.critical = critical + super().__init__(name, fmt_metric, result_cls) + + def evaluate(self, metric, resource): + if not metric.value and self.critical: + return self.result_cls(nagiosplugin.state.Critical, "NOT OK", metric) + elif not metric.value and not self.critical: + return self.result_cls(nagiosplugin.state.Warn, "NOT OK", metric) + else: + return self.result_cls(nagiosplugin.state.Ok, "OK", metric) + + +class JournalLag(nagiosplugin.Resource): + """Check journal lag""" + + def __init__(self, cursorfile): + self.cursorfile = cursorfile + + def parse_cursor(self, cursor): + """Parse a journald cursor entry""" + entries = cursor.strip().split(';') + ret = {} + for entry in entries: + key, value = entry.split('=') + ret[key] = value + + for key in ('i', 'm', 't'): + # Those cursor keys are hexadecimal + if key in ret: + ret[key] = int(ret[key], 16) + + return ret + + def get_file_journal_cursor(self): + _log.info("querying the journal cursor cache file %s" % self.cursorfile) + try: + with open(self.cursorfile, 'r') as f: + ret = f.read().strip() + except OSError as e: + raise nagiosplugin.CheckError("failed to read journal cursor file: %s" % e) + else: + _log.debug("current journal cursor: %s" % ret) + return ret + + def get_system_journal_cursor(self): + _log.info("querying the system journal for the current cursor") + reader = systemd.journal.Reader() + reader.seek_tail() + ret = reader.get_previous()['__CURSOR'] + _log.debug("current journald cursor: %s" % ret) + return ret + + def probe(self): + file_cursor = self.parse_cursor(self.get_file_journal_cursor()) + _log.debug("parsed journal cursor: %s" % file_cursor) + + system_cursor = self.parse_cursor(self.get_system_journal_cursor()) + _log.debug("parsed system cursor: %s" % system_cursor) + + sameboot = system_cursor['b'] == file_cursor['b'] + seqnum_lag = system_cursor['i'] - file_cursor['i'] if sameboot else 0 + monotonic_lag = system_cursor['m'] - file_cursor['m'] if sameboot else 0 + realtime_lag = system_cursor['t'] - file_cursor['t'] + + return [ + nagiosplugin.Metric('sameboot', sameboot, context='sameboot'), + nagiosplugin.Metric('entries_lag', seqnum_lag, context='lag_entries'), + nagiosplugin.Metric('monotonic_lag', monotonic_lag / 1000000, uom='s', context='lag_time'), + nagiosplugin.Metric('realtime_lag', realtime_lag / 1000000, uom='s', context='lag_time'), + ] + +class JournalSummary(nagiosplugin.Summary): + def ok(self, results): + return ', '.join([ + self.temp_lag_display(results), + self.items_lag_display(results), + ]) + def items_lag_display(self, results): + entries = results['entries_lag'].metric.value + return '%s %s behind' % (entries, 'entries' if entries != 1 else 'entry') + def temp_lag_display(self, results): + return '%s behind' % str(results['monotonic_lag'].metric) + +@nagiosplugin.guarded +def main(): + argp = argparse.ArgumentParser(description=__doc__) + argp.add_argument('-v', '--verbose', action='count', default=0, + help='increase output verbosity (use up to 3 times)') + argp.add_argument('-f', '--file', metavar='FILE', default='/var/lib/journalbeat/cursor-state', + help='read journald cursor state from this file') + argp.add_argument('-w', '--warning', metavar='RANGE', default='1200', + help='return warning if temporal lag is outside RANGE') + argp.add_argument('-c', '--critical', metavar='RANGE', default='3600', + help='return critical if temporal lag is outside RANGE') + argp.add_argument('-wn', '--warning-entries', metavar='RANGE', default='', + help='return warning if entries lag is outside RANGE') + argp.add_argument('-cn', '--critical-entries', metavar='RANGE', default='', + help='return critical if entries lag is outside RANGE') + + args = argp.parse_args() + + check = nagiosplugin.Check( + JournalLag(args.file), + BooleanContext('sameboot'), + ScalarContext('lag_time', args.warning, args.critical), + ScalarContext('lag_entries', args.warning_entries, args.critical_entries), + JournalSummary(), + ) + check.name = 'JOURNAL LAG' + check.main(verbose=args.verbose) + +if __name__ == '__main__': + main() diff --git a/site-modules/profile/files/munin/rabbitmq/rabbitmq_connections b/site-modules/profile/files/munin/rabbitmq/rabbitmq_connections new file mode 100755 index 00000000..8b003de2 --- /dev/null +++ b/site-modules/profile/files/munin/rabbitmq/rabbitmq_connections @@ -0,0 +1,99 @@ +#!/bin/bash + +: << =cut + +=head1 NAME + +rabbitmq_connections - monitor the number of connections to RabbitMQ + +=head1 CONFIGURATION + +You will need to add configuration to +/etc/munin/plugin-conf.d/rabbitmq_connection.conf for this plugin to +work. + +=over 2 + +=item C + +Required. Valid choices are C and C. This is required +by C. + +=item C + +Optional, default value is 500 + +=item C + +Optional, default value is 1000 + +=back + +=head2 EXAMPLE CONFIGURATION + + [rabbitmq_connections] + user rabbitmq + env.conn_warn 512 + env.conn_crit 1024 + +=head1 MAGIC MARKERS + + #%# family=contrib + +=cut + +case $(whoami) in + rabbitmq|root) + ;; + *) + echo 'Error: Plugin requires "user" to be set in plugin configuration.' >&2 + echo 'See "munindoc rabbitmq_connections" for more information' >&2 + exit 1 + ;; +esac + +# If run with the "config"-parameter, give out information on how the +# graphs should look. + +if [ "$1" = "config" ]; then + CONN_WARN=${conn_warn:-500} + CONN_CRIT=${conn_crit:-1000} + + # The host name this plugin is for. (Can be overridden to have + # one machine answer for several) + + # The title of the graph + echo 'graph_title RabbitMQ connections' + # Arguments to "rrdtool graph". In this case, tell it that the + # lower limit of the graph is '0', and that 1k=1000 (not 1024) + echo 'graph_args --base 1000 -l 0' + # The Y-axis label + echo 'graph_vlabel connections' + # We want Cur/Min/Avg/Max unscaled (i.e. 0.42 load instead of + # 420 milliload) + #echo 'graph_scale no' + echo 'graph_category RabbitMQ' + + echo "connections.label Connections" + echo "connections.warning $CONN_WARN" + echo "connections.critical $CONN_CRIT" + echo "connections.info Number of active connections" + + echo 'graph_info Shows the number of connections to RabbitMQ' + # Last, if run with the "config"-parameter, quit here (don't + # display any data) + exit 0 +fi + +# If not run with any parameters at all (or only unknown ones), do the +# real work - i.e. display the data. Almost always this will be +# "value" subfield for every data field. + +if hash rabbitmqctl >/dev/null 2>&1; then + connections=$(HOME=/tmp rabbitmqctl list_connections state | grep -c running) +else + echo "$0: Could not run rabbitmqctl" >&2 + connections=U +fi + +printf "connections.value %s\n" "$connections" diff --git a/site-modules/profile/files/munin/rabbitmq/rabbitmq_consumers b/site-modules/profile/files/munin/rabbitmq/rabbitmq_consumers new file mode 100755 index 00000000..92a59d34 --- /dev/null +++ b/site-modules/profile/files/munin/rabbitmq/rabbitmq_consumers @@ -0,0 +1,78 @@ +#!/bin/bash +# +# Plugin to monitor the queues of a virtual_host in RabbitMQ +# +# Usage: Link or copy into /etc/munin/node.d/ +# +# Parameters +# env.vhost +# env.queue_warn +# env.queue_crit +# +# Magic markers (optional - only used by munin-config and some +# installation scripts): +# +#%# family=auto +#%# capabilities=autoconf + +# If run with the "autoconf"-parameter, give our opinion on whether we +# should be run on this system or not. This is optinal, and only used by +# munin-config. In the case of this plugin, we should most probably +# always be included. + +if [ "$1" = "autoconf" ]; then + echo yes + exit 0 +fi + +# If run with the "config"-parameter, give out information on how the +# graphs should look. + +HOME=/tmp/ +VHOST=${vhost:-"/"} +FILTER=${filter:-"^(amq\.gen-.*|celery@.*\.pidbox|celeryev\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"} +QUEUES=$(HOME=$HOME rabbitmqctl list_queues -p $VHOST name | \ + grep -v '^Listing' | \ + grep -v 'done\.$' | \ + grep -Ev $FILTER | \ + sed -e 's/[.=-]/_/g' ) + +if [ "$1" = "config" ]; then + QUEUE_WARN=${queue_warn:-100} + QUEUE_CRIT=${queue_crit:-500} + + # The host name this plugin is for. (Can be overridden to have + # one machine answer for several) + + # The title of the graph + echo "graph_title RabbitMQ $VHOST consumers" + # Arguments to "rrdtool graph". In this case, tell it that the + # lower limit of the graph is '0', and that 1k=1000 (not 1024) + echo 'graph_args --base 1000 -l 0' + # The Y-axis label + echo 'graph_vlabel consumers' + # We want Cur/Min/Avg/Max unscaled (i.e. 0.42 load instead of + # 420 milliload) + #echo 'graph_scale no' + echo 'graph_category RabbitMQ' + + for queue in $QUEUES; do + echo "$queue.label $queue" + echo "$queue.warning $QUEUE_WARN" + echo "$queue.critical $QUEUE_CRIT" + echo "$queue.info Active consumers for $queue" + done + + echo 'graph_info Lists active consumers for a queue.' + # Last, if run with the "config"-parameter, quit here (don't + # display any data) + exit 0 +fi + +# If not run with any parameters at all (or only unknown ones), do the +# real work - i.e. display the data. Almost always this will be +# "value" subfield for every data field. + +HOME=$HOME rabbitmqctl list_queues -p $VHOST name consumers| \ + grep -v "^Listing" | grep -v "done.$" | grep -Ev $FILTER | \ + perl -nle'($q, $s) = split; $q =~ s/[.=-]/_/g; print("$q.value $s")' diff --git a/site-modules/profile/files/munin/rabbitmq/rabbitmq_messages b/site-modules/profile/files/munin/rabbitmq/rabbitmq_messages new file mode 100755 index 00000000..7c592589 --- /dev/null +++ b/site-modules/profile/files/munin/rabbitmq/rabbitmq_messages @@ -0,0 +1,78 @@ +#!/bin/bash +# +# Plugin to monitor the queues of a virtual_host in RabbitMQ +# +# Usage: Link or copy into /etc/munin/node.d/ +# +# Parameters +# env.vhost +# env.queue_warn +# env.queue_crit +# +# Magic markers (optional - only used by munin-config and some +# installation scripts): +# +#%# family=auto +#%# capabilities=autoconf + +# If run with the "autoconf"-parameter, give our opinion on whether we +# should be run on this system or not. This is optinal, and only used by +# munin-config. In the case of this plugin, we should most probably +# always be included. + +if [ "$1" = "autoconf" ]; then + echo yes + exit 0 +fi + +# If run with the "config"-parameter, give out information on how the +# graphs should look. + +HOME=/tmp/ +VHOST=${vhost:-"/"} +FILTER=${filter:-"^(amq\.gen-.*|celery@.*\.pidbox|celeryev\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"} +QUEUES=$(HOME=$HOME rabbitmqctl list_queues -p $VHOST name | \ + grep -v '^Listing' | \ + grep -v 'done\.$' | \ + grep -Ev $FILTER | \ + sed -e 's/[.=-]/_/g' ) + +if [ "$1" = "config" ]; then + QUEUE_WARN=${queue_warn:-10000} + QUEUE_CRIT=${queue_crit:-20000} + + # The host name this plugin is for. (Can be overridden to have + # one machine answer for several) + + # The title of the graph + echo "graph_title RabbitMQ $VHOST list_queues" + # Arguments to "rrdtool graph". In this case, tell it that the + # lower limit of the graph is '0', and that 1k=1000 (not 1024) + echo 'graph_args --base 1000 -l 0' + # The Y-axis label + echo 'graph_vlabel queue_size' + # We want Cur/Min/Avg/Max unscaled (i.e. 0.42 load instead of + # 420 milliload) + #echo 'graph_scale no' + echo 'graph_category RabbitMQ' + + for queue in $QUEUES; do + echo "$queue.label $queue" + echo "$queue.warning $QUEUE_WARN" + echo "$queue.critical $QUEUE_CRIT" + echo "$queue.info Queue size for $queue" + done + + echo 'graph_info Lists how many messages are in each queue.' + # Last, if run with the "config"-parameter, quit here (don't + # display any data) + exit 0 +fi + +# If not run with any parameters at all (or only unknown ones), do the +# real work - i.e. display the data. Almost always this will be +# "value" subfield for every data field. + +HOME=$HOME rabbitmqctl list_queues -p $VHOST | \ + grep -v "^Listing" | grep -v "done.$" | grep -Ev $FILTER | \ + perl -nle'($q, $s) = split; $q =~ s/[.=-]/_/g; print("$q.value $s")' diff --git a/site-modules/profile/files/munin/rabbitmq/rabbitmq_messages_unacknowledged b/site-modules/profile/files/munin/rabbitmq/rabbitmq_messages_unacknowledged new file mode 100755 index 00000000..6aecfc5b --- /dev/null +++ b/site-modules/profile/files/munin/rabbitmq/rabbitmq_messages_unacknowledged @@ -0,0 +1,78 @@ +#!/bin/bash +# +# Plugin to monitor the queues of a virtual_host in RabbitMQ +# +# Usage: Link or copy into /etc/munin/node.d/ +# +# Parameters +# env.vhost +# env.queue_warn +# env.queue_crit +# +# Magic markers (optional - only used by munin-config and some +# installation scripts): +# +#%# family=auto +#%# capabilities=autoconf + +# If run with the "autoconf"-parameter, give our opinion on whether we +# should be run on this system or not. This is optinal, and only used by +# munin-config. In the case of this plugin, we should most probably +# always be included. + +if [ "$1" = "autoconf" ]; then + echo yes + exit 0 +fi + +# If run with the "config"-parameter, give out information on how the +# graphs should look. + +HOME=/tmp/ +VHOST=${vhost:-"/"} +FILTER=${filter:-"^(amq\.gen-.*|celery@.*\.pidbox|celeryev\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"} +QUEUES=$(HOME=$HOME rabbitmqctl list_queues -p $VHOST name | \ + grep -v '^Listing' | \ + grep -v 'done\.$' | \ + grep -Ev $FILTER | \ + sed -e 's/[.=-]/_/g' ) + +if [ "$1" = "config" ]; then + QUEUE_WARN=${queue_warn:-10000} + QUEUE_CRIT=${queue_crit:-20000} + + # The host name this plugin is for. (Can be overridden to have + # one machine answer for several) + + # The title of the graph + echo "graph_title RabbitMQ $VHOST Unacknowledged Messages" + # Arguments to "rrdtool graph". In this case, tell it that the + # lower limit of the graph is '0', and that 1k=1000 (not 1024) + echo 'graph_args --base 1000 -l 0' + # The Y-axis label + echo 'graph_vlabel unacknowledged' + # We want Cur/Min/Avg/Max unscaled (i.e. 0.42 load instead of + # 420 milliload) + #echo 'graph_scale no' + echo 'graph_category RabbitMQ' + + for queue in $QUEUES; do + echo "$queue.label $queue" + echo "$queue.warning $QUEUE_WARN" + echo "$queue.critical $QUEUE_CRIT" + echo "$queue.info Unacknowledged messages for $queue" + done + + echo 'graph_info Lists how many messages are in each queue.' + # Last, if run with the "config"-parameter, quit here (don't + # display any data) + exit 0 +fi + +# If not run with any parameters at all (or only unknown ones), do the +# real work - i.e. display the data. Almost always this will be +# "value" subfield for every data field. + +HOME=$HOME rabbitmqctl list_queues -p $VHOST name messages_unacknowledged | \ + grep -v "^Listing" | grep -v "done.$" | grep -Ev $FILTER | \ + perl -nle'($q, $s) = split; $q =~ s/[.=-]/_/g; print("$q.value $s")' diff --git a/site-modules/profile/files/munin/rabbitmq/rabbitmq_messages_uncommitted b/site-modules/profile/files/munin/rabbitmq/rabbitmq_messages_uncommitted new file mode 100755 index 00000000..56ff2357 --- /dev/null +++ b/site-modules/profile/files/munin/rabbitmq/rabbitmq_messages_uncommitted @@ -0,0 +1,78 @@ +#!/bin/bash +# +# Plugin to monitor the queues of a virtual_host in RabbitMQ +# +# Usage: Link or copy into /etc/munin/node.d/ +# +# Parameters +# env.vhost +# env.queue_warn +# env.queue_crit +# +# Magic markers (optional - only used by munin-config and some +# installation scripts): +# +#%# family=auto +#%# capabilities=autoconf + +# If run with the "autoconf"-parameter, give our opinion on whether we +# should be run on this system or not. This is optinal, and only used by +# munin-config. In the case of this plugin, we should most probably +# always be included. + +if [ "$1" = "autoconf" ]; then + echo yes + exit 0 +fi + +# If run with the "config"-parameter, give out information on how the +# graphs should look. + +HOME=/tmp/ +VHOST=${vhost:-"/"} +FILTER=${filter:-"^(amq\.gen-.*|celery@.*\.pidbox|celeryev\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"} +QUEUES=$(HOME=$HOME rabbitmqctl list_queues -p $VHOST name | \ + grep -v '^Listing' | \ + grep -v 'done\.$' | \ + grep -Ev $FILTER | \ + sed -e 's/[.=-]/_/g' ) + +if [ "$1" = "config" ]; then + QUEUE_WARN=${queue_warn:-10000} + QUEUE_CRIT=${queue_crit:-20000} + + # The host name this plugin is for. (Can be overridden to have + # one machine answer for several) + + # The title of the graph + echo "graph_title RabbitMQ $VHOST Uncommitted Messages" + # Arguments to "rrdtool graph". In this case, tell it that the + # lower limit of the graph is '0', and that 1k=1000 (not 1024) + echo 'graph_args --base 1000 -l 0' + # The Y-axis label + echo 'graph_vlabel uncommitted' + # We want Cur/Min/Avg/Max unscaled (i.e. 0.42 load instead of + # 420 milliload) + #echo 'graph_scale no' + echo 'graph_category RabbitMQ' + + for queue in $QUEUES; do + echo "$queue.label $queue" + echo "$queue.warning $QUEUE_WARN" + echo "$queue.critical $QUEUE_CRIT" + echo "$queue.info Uncommitted messages for $queue" + done + + echo 'graph_info Lists how many messages are in each queue.' + # Last, if run with the "config"-parameter, quit here (don't + # display any data) + exit 0 +fi + +# If not run with any parameters at all (or only unknown ones), do the +# real work - i.e. display the data. Almost always this will be +# "value" subfield for every data field. + +HOME=$HOME rabbitmqctl list_channels -p $VHOST name messages_uncommitted | \ + grep -v "^Listing" | grep -v "done.$" | grep -Ev $FILTER | \ + perl -nle'($q, $s) = split; $q =~ s/[.=-]/_/g; print("$q.value $s")' diff --git a/site-modules/profile/files/munin/rabbitmq/rabbitmq_queue_memory b/site-modules/profile/files/munin/rabbitmq/rabbitmq_queue_memory new file mode 100755 index 00000000..36433197 --- /dev/null +++ b/site-modules/profile/files/munin/rabbitmq/rabbitmq_queue_memory @@ -0,0 +1,78 @@ +#!/bin/bash +# +# Plugin to monitor the queues of a virtual_host in RabbitMQ +# +# Usage: Link or copy into /etc/munin/node.d/ +# +# Parameters +# env.vhost +# env.queue_warn +# env.queue_crit +# +# Magic markers (optional - only used by munin-config and some +# installation scripts): +# +#%# family=auto +#%# capabilities=autoconf + +# If run with the "autoconf"-parameter, give our opinion on whether we +# should be run on this system or not. This is optinal, and only used by +# munin-config. In the case of this plugin, we should most probably +# always be included. + +if [ "$1" = "autoconf" ]; then + echo yes + exit 0 +fi + +# If run with the "config"-parameter, give out information on how the +# graphs should look. + +HOME=/tmp/ +VHOST=${vhost:-"/"} +FILTER=${filter:-"^(amq\.gen-.*|celery@.*\.pidbox|celeryev\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"} +QUEUES=$(HOME=$HOME rabbitmqctl list_queues -p $VHOST name | \ + grep -v '^Listing' | \ + grep -v 'done\.$' | \ + grep -Ev $FILTER | \ + sed -e 's/[.=-]/_/g' ) + +if [ "$1" = "config" ]; then + QUEUE_WARN=${queue_warn:-104857600} # 100 MB + QUEUE_CRIT=${queue_crit:-209715200} # 200 MB + + # The host name this plugin is for. (Can be overridden to have + # one machine answer for several) + + # The title of the graph + echo "graph_title RabbitMQ $VHOST Memory used by queue" + # Arguments to "rrdtool graph". In this case, tell it that the + # lower limit of the graph is '0', and that 1k=1000 (not 1024) + echo 'graph_args --base 1024 --vertical-label Bytes -l 0' + # The Y-axis label + echo 'graph_vlabel memory' + # We want Cur/Min/Avg/Max unscaled (i.e. 0.42 load instead of + # 420 milliload) + #echo 'graph_scale no' + echo 'graph_category RabbitMQ' + + for queue in $QUEUES; do + echo "$queue.label $queue" + echo "$queue.warning $QUEUE_WARN" + echo "$queue.critical $QUEUE_CRIT" + echo "$queue.info Memory used by $queue" + done + + echo 'graph_info Show memory usage by queue' + # Last, if run with the "config"-parameter, quit here (don't + # display any data) + exit 0 +fi + +# If not run with any parameters at all (or only unknown ones), do the +# real work - i.e. display the data. Almost always this will be +# "value" subfield for every data field. + +HOME=$HOME rabbitmqctl list_queues -p $VHOST name memory | \ + grep -v "^Listing" | grep -v "done.$" | \ + perl -nle'($q, $s) = split; $q =~ s/[.=-]/_/g; print("$q.value $s")' diff --git a/site-modules/profile/files/munin/stats_export/export-rrd b/site-modules/profile/files/munin/stats_export/export-rrd new file mode 100755 index 00000000..78c44c9e --- /dev/null +++ b/site-modules/profile/files/munin/stats_export/export-rrd @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 + +"""Script to execute the export of softwareheritage's rrds data. + +""" + +import click +import json +import os +import subprocess + + +DIRPATH='/var/lib/munin/softwareheritage.org/' +FILENAME_PATTERN="prado.softwareheritage.org-softwareheritage_objects_softwareheritage-###-g.rrd" +# The data source used at rrd creation time +DS=42 + +ENTITIES=[ + "content", + "origin", + "revision", + # "directory_entry_dir", + # "directory_entry_file", + # "directory_entry_rev", + # "directory", + # "entity", + # "occurrence_history", + # "person", + # "project", + # "release", + # "revision_history", + # "skipped_content", + # "visit", +] + +def compute_cmd(dirpath, + start, + step=86400): + """Compute the command to execute to retrieve the needed data. + + Returns: + The command as string. + + """ + cmd = ['rrdtool', 'xport', '--json', '--start', str(start), '--end', 'now-1d', + '--step', str(step)] + for entity in ENTITIES: + filename = FILENAME_PATTERN.replace('###', entity) + filepath = os.path.join(dirpath, filename) + + if os.path.exists(filepath): + cmd.extend(['DEF:out-%s1=%s:%s:AVERAGE' % (entity, filepath, DS), + 'XPORT:out-%s1:%s' % (entity, entity)]) + + return cmd + + +def retrieve_json(cmd): + """Given the cmd command, execute and returns the right json format. + + Args: + cmd: the command to execute to retrieve the desired json. + + Returns: + The desired result as json string. + """ + cmdpipe = subprocess.Popen(cmd, stdout=subprocess.PIPE) + data = b'' + while True: + line = cmdpipe.stdout.readline() + if not line: + break + # Hack: the json output is not well-formed... + line = line.replace(b'\'', b'"') + line = line.replace(b'about: ', b'"about": ') + line = line.replace(b'meta:', b'"meta": ') + data += line + + cmdpipe.stdout.close() + return json.loads(data.decode('utf-8')) + + +def prepare_data(data): + """Prepare the data with x,y coordinate. + + x is the time, y is the actual value. + """ + # javascript has a ratio of 1000... + step = data['meta']['step'] * 1000 # nb of milliseconds + start_ts = data['meta']['start'] * 1000 # starting ts + + legends = data['meta']['legend'] + + # The legends, something like + # ["content-avg", "content-min", "content-max", "directory_entry_dir-avg", ...] + r = {} + day_ts = start_ts + for day, values in enumerate(data['data']): + day_ts += step + for col, value in enumerate(values): + if value is None: + continue + legend_col = legends[col] + l = r.get(legend_col, []) + l.append((day_ts, value)) + r[legend_col] = l + + return r + + +@click.command() +@click.option('--dirpath', default=DIRPATH, help="Default path to look for rrd files.") +@click.option('--start', default=1434499200, help="Default starting timestamp") # Default to 2015-05-12T16:51:25Z +@click.option('--step', default=86400, help="Compute the data step (default to 86400).") +def main(dirpath, start, step): + + # Delegate the execution to the system + run_cmd = compute_cmd(dirpath, start, step) + data = retrieve_json(run_cmd) + + # Format data + data = prepare_data(data) + + print(json.dumps(data)) + + +if __name__ == '__main__': + main() diff --git a/site-modules/profile/files/prometheus/sql/update-prometheus-sql-exporter-config b/site-modules/profile/files/prometheus/sql/update-prometheus-sql-exporter-config new file mode 100755 index 00000000..e1a51f58 --- /dev/null +++ b/site-modules/profile/files/prometheus/sql/update-prometheus-sql-exporter-config @@ -0,0 +1,164 @@ +#!/usr/bin/python3 +# +# Originally part of Credativ's Elephant Shed +# https://github.com/credativ/elephant-shed +# prometheus/sql_exporter/update-prometheus-sql-exporter-config +# Licensed under the GPLv3. +# +# Adapted to run on Python 3.5 + +import sys +import yaml +import subprocess +import traceback +from pkg_resources import parse_version + +""" +Returns a list of clusters (dict) containing the following attributes: + - name + - version + - port + - status + - owner + - databases (dict) + +Calls get_databases for each cluster. +""" +def get_clusters(min_version=None, max_version=None): + clusters = list() + + proc = subprocess.Popen(["pg_lsclusters"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, universal_newlines=True) + (out, err) = proc.communicate() + + out = out.rstrip("\n") + out_lines = out.splitlines() + + for i in range(1,len(out_lines)): + cluster = dict() + version, name, port, status, owner = out_lines[i].split()[:5] + cluster["version"] = version + cluster["name"] = name + cluster["port"] = port + cluster["status"] = status + cluster["owner"] = owner + cluster["databases"] = get_databases(cluster) + clusters.append(cluster) + + return clusters + +""" +Returns a list of databases for the given cluster. +""" +def get_databases(cluster): + databases = list() + command = "sudo -u %s psql -p %s -tXA -c \"SELECT datname FROM pg_database WHERE NOT datname ~ '^template(0|1)$';\"" + command = command % (cluster["owner"], cluster["port"]) + proc = subprocess.Popen([command], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, universal_newlines=True) + (out, err) = proc.communicate() + out_lines = out.splitlines() + for line in out_lines: + databases.append(line.split("|")[0]) + + return databases + +""" +Returns the a config element (dict). +""" +def read_config_template(): + config_filename = "/etc/prometheus-sql-exporter.yml.in" + with open(config_filename, "r") as f: + yaml_conf = yaml.load(f) + + return yaml_conf + +""" +Writes the given config to file. +""" +def write_config(conf): + config_filename = "/etc/prometheus-sql-exporter.yml" + with open(config_filename, "w") as f: + yaml.dump(conf, f) + + return True + +""" +Takes a given config and appends connection strings to it. +""" +def append_conn_strings_to_template(conf): + clusters = get_clusters() + + for job in conf["jobs"]: + min_version = parse_version("0") + max_version = parse_version("99999999999") + used_clusters = list() + conn_strings = list() + + if "min_version" in job: + min_version = parse_version(job["min_version"]) + + if "max_version" in job: + max_version = parse_version(job["max_version"]) + + for cluster in clusters: + cluster_version = parse_version(cluster["version"]) + if cluster_version >= min_version and cluster_version <= max_version: + used_clusters.append(cluster) + + if job['name'].startswith('cluster'): + for cluster in used_clusters: + conn_strings.extend(build_conn_strings(cluster, False)) + elif job['name'].startswith('database'): + for cluster in used_clusters: + conn_strings.extend(build_conn_strings(cluster, True)) + else: + conn_strings.extend(job['connections']) + + job["connections"] = conn_strings + + return conf + +""" +Returns a list of connection strings for all clusters/databases. + +If per_db is True a list of all databases is returned. Otherwise a list of all +clusters (using template1) is returned. +""" +def build_conn_strings(cluster, per_db=True): + conn_strings = list() + + if per_db: + for db in cluster["databases"]: + conn_string = 'postgres://%s@:%s/%s?sslmode=disable' + conn_string = conn_string % (cluster["owner"], cluster["port"], db) + conn_strings.append(conn_string) + else: + conn_string = 'postgres://%s@:%s/postgres?sslmode=disable' + conn_string = conn_string % (cluster["owner"], cluster["port"]) + conn_strings.append(conn_string) + + return conn_strings + +if __name__ == "__main__": + clusters = get_clusters() + + try: + yaml_conf = read_config_template() + except: + sys.stderr.write("Could not read config template.\n") + print('-'*60) + traceback.print_exc(file=sys.stdout) + print('-'*60) + exit(1) + + try: + yaml_conf = append_conn_strings_to_template(yaml_conf) + except: + sys.stderr.write("Could not write new config.\n") + print('-'*60) + traceback.print_exc(file=sys.stdout) + print('-'*60) + exit(1) + + write_config(yaml_conf) + + exit(0) diff --git a/site-modules/profile/files/swh/deploy/worker/swh-worker-generator b/site-modules/profile/files/swh/deploy/worker/swh-worker-generator new file mode 100755 index 00000000..2e0bd77c --- /dev/null +++ b/site-modules/profile/files/swh/deploy/worker/swh-worker-generator @@ -0,0 +1,22 @@ +#!/bin/sh + +# This systemd generator creates dependency symlinks that make all swh-worker +# instances in /etc/softwareheritage/worker/ be started/stopped/reloaded when +# swh-worker.service is started/stopped/reloaded. + +set -eu + +gendir="$1" +wantdir="$1/swh-worker.service.wants" +swhworkerservice="/etc/systemd/system/swh-worker@.service" + +mkdir -p "$wantdir" + +for conf in /etc/softwareheritage/worker/*.ini; do + test -e "$conf" || continue + base=$(basename $conf) + instancename=$(basename $base .ini) + ln -s "$swhworkerservice" "$wantdir/swh-worker@$instancename.service" +done + +exit 0 diff --git a/site-modules/profile/files/swh/deploy/worker/swh-worker.service b/site-modules/profile/files/swh/deploy/worker/swh-worker.service new file mode 100644 index 00000000..0e29f431 --- /dev/null +++ b/site-modules/profile/files/swh/deploy/worker/swh-worker.service @@ -0,0 +1,11 @@ +[Unit] +Description=Software Heritage Worker (meta-task) + +[Service] +Type=oneshot +ExecStart=/bin/true +ExecReload=/bin/true +RemainAfterExit=on + +[Install] +WantedBy=multi-user.target diff --git a/site-modules/profile/files/swh/deploy/worker/swh-worker@.service b/site-modules/profile/files/swh/deploy/worker/swh-worker@.service new file mode 100644 index 00000000..ef55b70e --- /dev/null +++ b/site-modules/profile/files/swh/deploy/worker/swh-worker@.service @@ -0,0 +1,24 @@ +[Unit] +Description=Software Heritage Worker (%i) +After=network.target + +[Service] +User=swhworker +Group=swhworker + +Type=simple +Environment=SWH_WORKER_INSTANCE=%i +Environment=CONCURRENCY=10 +Environment=MAX_TASKS_PER_CHILD=5 +Environment=LOGLEVEL=info +ExecStart=/usr/bin/python3 -m celery worker --app=swh.scheduler.celery_backend.config.app --pool=prefork --events --concurrency=${CONCURRENCY} --maxtasksperchild=${MAX_TASKS_PER_CHILD} -Ofair --loglevel=${LOGLEVEL} --without-gossip --without-mingle --without-heartbeat -n %i.%%h + +KillMode=process +KillSignal=SIGTERM +TimeoutStopSec=0 + +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git "a/site-modules/profile/files/swh/deploy/worker/system-swh\\x2dworker.slice" "b/site-modules/profile/files/swh/deploy/worker/system-swh\\x2dworker.slice" new file mode 100644 index 00000000..1696b625 --- /dev/null +++ "b/site-modules/profile/files/swh/deploy/worker/system-swh\\x2dworker.slice" @@ -0,0 +1,5 @@ +[Unit] +Description=SWH workers + +[Slice] +MemoryMax=90% diff --git a/site-modules/profile/files/unbound/insecure.conf b/site-modules/profile/files/unbound/insecure.conf new file mode 100644 index 00000000..0abfe714 --- /dev/null +++ b/site-modules/profile/files/unbound/insecure.conf @@ -0,0 +1,5 @@ +# File managed by Puppet (class profile::unbound), modifications will be lost. +# Our upstream DNS servers don't support DNSSEC; make them permissive + +server: + val-permissive-mode: yes diff --git a/site-modules/profile/files/varnish/synth_redirect.vcl b/site-modules/profile/files/varnish/synth_redirect.vcl new file mode 100644 index 00000000..adb8ff79 --- /dev/null +++ b/site-modules/profile/files/varnish/synth_redirect.vcl @@ -0,0 +1,19 @@ +# synth_redirect.vcl +# +# Redirect to the x-redir http header when receiving a synthesized code 850 +# +# Example use: +# sub vcl_recv { +# set req.http.x-redir = "https://" + req.http.host + req.url; +# return(synth(850, "Moved permanently")); +# } +# +# File managed by puppet. All modifications will be lost. + +sub vcl_synth { + if (resp.status == 850) { + set resp.http.Location = req.http.x-redir; + set resp.status = 302; + return (deliver); + } +} diff --git a/site-modules/profile/lib/facter/mounts.rb b/site-modules/profile/lib/facter/mounts.rb new file mode 100644 index 00000000..56f9d730 --- /dev/null +++ b/site-modules/profile/lib/facter/mounts.rb @@ -0,0 +1,61 @@ +begin + Facter.add("mounts") do + ignorefs = [ + "NFS", + "afs", + "autofs", + "binfmt_misc", + "cgroup", + "cifs", + "coda", + "configfs", + "debugfs", + "devfs", + "devpts", + "devtmpfs", + "efivarfs", + "ftpfs", + "fuse", + "fuse.gvfsd-fuse", + "fuse.lxcfs", + "fuse.snapshotfs", + "fusectl", + "hugetlbfs", + "iso9660", + "lustre_lite", + "mfs", + "mqueue", + "ncpfs", + "nfs", + "nfs4", + "nfsd", + "proc", + "pstore", + "rpc_pipefs", + "securityfs", + "shfs", + "smbfs", + "sysfs", + "tmpfs", + "tracefs", + "udf", + "usbfs", + ].uniq.sort.join(',') + + mountpoints = [] + + Facter::Util::Resolution.exec("findmnt --list --noheadings -o TARGET,SOURCE --invert --types #{ignorefs}").lines.each do |line| + mountpoint, source = line.chomp.split + # bind mounts + if not source.end_with?(']') + mountpoints << mountpoint + end + end + + setcode do + mountpoints + end + end + +rescue Exception => _ +end diff --git a/site-modules/profile/lib/facter/swh_hostname.rb b/site-modules/profile/lib/facter/swh_hostname.rb new file mode 100644 index 00000000..96f7a621 --- /dev/null +++ b/site-modules/profile/lib/facter/swh_hostname.rb @@ -0,0 +1,19 @@ +require 'puppet' +require 'socket' + +domain_name = ".internal.softwareheritage.org" + +Facter.add(:swh_hostname) do + setcode do + retval = {} + retval["fqdn"] = Facter.value(:fqdn).to_s + if retval["fqdn"].end_with?(domain_name) + retval["short"] = retval["fqdn"].chomp(domain_name) + retval["internal_fqdn"] = retval["fqdn"] + else + retval["short"] = Socket.gethostname + retval["internal_fqdn"] = retval["short"] + domain_name + end + retval + end +end diff --git a/site-modules/profile/lib/puppet/functions/flatten_to_argument_list.rb b/site-modules/profile/lib/puppet/functions/flatten_to_argument_list.rb new file mode 100644 index 00000000..a718f8da --- /dev/null +++ b/site-modules/profile/lib/puppet/functions/flatten_to_argument_list.rb @@ -0,0 +1,35 @@ +require 'shellwords' + +Puppet::Functions.create_function(:flatten_to_argument_list) do + dispatch :flatten_to_argument_list do + param 'Hash', :variable + optional_param 'String', :escaping_type + optional_param 'String', :prefix + return_type 'Array[String]' + end + + def flatten_to_argument_list(variable, escaping_type = 'systemd', prefix = '--') + ret = [] + variable.each do |key, value| + arg = "#{prefix}#{key}".gsub('_', '-') + if Hash === value + ret += flatten_to_argument_list(value, escaping_type, "#{arg}.") + else + if value == true + ret.push(arg) + else + if escaping_type == 'systemd' + # This replaces every backslash with four backslashes to please + # systemd's EnvironmentFile escaping. Yes, gsub needs four + # backslashes per output backslash. + value.gsub!('\\', '\\\\\\\\\\\\\\\\') + elsif escaping_type == 'shell' + value = Shellwords.escape(value) + end + ret.push("#{arg}=#{value}") + end + end + end + ret + end +end diff --git a/site-modules/profile/lib/puppet/functions/inline_yaml.rb b/site-modules/profile/lib/puppet/functions/inline_yaml.rb new file mode 100644 index 00000000..5f93d12f --- /dev/null +++ b/site-modules/profile/lib/puppet/functions/inline_yaml.rb @@ -0,0 +1,31 @@ +require 'yaml' + +Puppet::Functions.create_function(:inline_yaml) do + dispatch :from_variable do + param 'Variant[Hash, Array]', :variable + optional_param 'Hash', :parameters + return_type 'String' + end + + def from_variable(variable, parameters = {}) + params = { + 'header' => '# File managed by puppet - modifications will be lost', + 'indent_lines' => 0, + }.merge(parameters) + + header = params['header'] + indent_lines = params['indent_lines'] + + data = YAML.dump(variable).lines[1..-1].join.rstrip << "\n" + if indent_lines + data = data.each_line { |l| (' ' * indent_lines) + l } + end + + if header + "#{header}\n#{data}" + else + data + end + end +end + diff --git a/site-modules/profile/lib/puppet/parser/functions/ip_for_network.rb b/site-modules/profile/lib/puppet/parser/functions/ip_for_network.rb new file mode 100644 index 00000000..011e486a --- /dev/null +++ b/site-modules/profile/lib/puppet/parser/functions/ip_for_network.rb @@ -0,0 +1,35 @@ +require "ipaddr" + +module Puppet::Parser::Functions + + newfunction(:ip_for_network, :type => :rvalue, :doc => <<-EOS +Returns an ip address for the given network in cidr notation + +ip_for_network("127.0.0.0/24") => 127.0.0.1 + EOS + ) do |args| + addresses_in_range = [] + ip_addresses = [] + interfaces = [] + + range = IPAddr.new(args[0]) + interfaces = lookupvar('interfaces').split(",") + interfaces.each do |i| + ip = lookupvar("ipaddress_#{i}") + unless ip.nil? + ip_addresses.push(ip) + end + end + + ip_addresses.each do |string_address| + ip_address = IPAddr.new(string_address) + if range.include?(ip_address) + addresses_in_range.push(string_address) + end + end + + # TODO don't be a dork dork with the return + # handle multiple values! + return addresses_in_range.first + end +end diff --git a/site-modules/profile/lib/puppet/parser/functions/reverse_ipv4.rb b/site-modules/profile/lib/puppet/parser/functions/reverse_ipv4.rb new file mode 100644 index 00000000..94777cca --- /dev/null +++ b/site-modules/profile/lib/puppet/parser/functions/reverse_ipv4.rb @@ -0,0 +1,15 @@ +require "ipaddr" + +module Puppet::Parser::Functions + + newfunction(:reverse_ipv4, :type => :rvalue, :doc => <<-EOS +Returns the in-addr.arpa hostname for a given ip address + +reverse_ipv4('192.168.1.1') => '1.1.168.192.in-addr.arpa' + EOS + ) do |args| + + address = IPAddr.new(args[0]) + return address.reverse() + end +end diff --git a/site-modules/profile/manifests/annex_web.pp b/site-modules/profile/manifests/annex_web.pp new file mode 100644 index 00000000..b10e51fb --- /dev/null +++ b/site-modules/profile/manifests/annex_web.pp @@ -0,0 +1,123 @@ +# Deployment of web-facing public Git-annex +class profile::annex_web { + + $annex_basepath = lookup('annex::basepath') + + $annex_vhost_name = lookup('annex::vhost::name') + $annex_vhost_docroot = lookup('annex::vhost::docroot') + $annex_vhost_basic_auth_file = "${annex_basepath}/http_auth" + $annex_vhost_basic_auth_content = lookup('annex::vhost::basic_auth_content') + $annex_vhost_ssl_protocol = lookup('annex::vhost::ssl_protocol') + $annex_vhost_ssl_honorcipherorder = lookup('annex::vhost::ssl_honorcipherorder') + $annex_vhost_ssl_cipher = lookup('annex::vhost::ssl_cipher') + $annex_vhost_hsts_header = lookup('annex::vhost::hsts_header') + + include ::profile::ssl + include ::profile::apache::common + + ::apache::vhost {"${annex_vhost_name}_non-ssl": + servername => $annex_vhost_name, + port => '80', + docroot => $annex_vhost_docroot, + redirect_status => 'permanent', + redirect_dest => "https://${annex_vhost_name}/", + } + + $ssl_cert_name = 'star_softwareheritage_org' + $ssl_cert = $::profile::ssl::certificate_paths[$ssl_cert_name] + $ssl_chain = $::profile::ssl::chain_paths[$ssl_cert_name] + $ssl_key = $::profile::ssl::private_key_paths[$ssl_cert_name] + + ::apache::vhost {"${annex_vhost_name}_ssl": + servername => $annex_vhost_name, + port => '443', + ssl => true, + ssl_protocol => $annex_vhost_ssl_protocol, + ssl_honorcipherorder => $annex_vhost_ssl_honorcipherorder, + ssl_cipher => $annex_vhost_ssl_cipher, + ssl_cert => $ssl_cert, + ssl_chain => $ssl_chain, + ssl_key => $ssl_key, + headers => [$annex_vhost_hsts_header], + docroot => $annex_vhost_docroot, + directories => [{ + 'path' => $annex_vhost_docroot, + 'require' => 'all granted', + 'options' => ['Indexes', 'FollowSymLinks', 'MultiViews'], + }, + { # hide (annex) .git directory + 'path' => '.*/\.git/?$', + 'provider' => 'directorymatch', + 'require' => 'all denied', + }], + require => [ + File[$ssl_cert], + File[$ssl_chain], + File[$ssl_key], + ], + } + + file {"${annex_vhost_docroot}/public": + ensure => link, + target => "../annexroot/public", + require => File[$annex_vhost_docroot], + } + + file {$annex_vhost_basic_auth_file: + ensure => present, + owner => 'root', + group => 'www-data', + mode => '0640', + content => '$annex_vhost_basic_auth_content', + } + + + $icinga_checks_file = '/etc/icinga2/conf.d/exported-checks.conf' + + @@::icinga2::object::service {"annex http redirect on ${::fqdn}": + service_name => 'annex http redirect', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $annex_vhost_name, + http_vhost => $annex_vhost_name, + http_uri => '/', + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + @@::icinga2::object::service {"annex https on ${::fqdn}": + service_name => 'annex https', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $annex_vhost_name, + http_vhost => $annex_vhost_name, + http_ssl => true, + http_sni => true, + http_uri => '/', + http_onredirect => sticky + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + @@::icinga2::object::service {"annex https certificate ${::fqdn}": + service_name => 'annex https certificate', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $annex_vhost_name, + http_vhost => $annex_vhost_name, + http_ssl => true, + http_sni => true, + http_certificate => 60, + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } +} diff --git a/site-modules/profile/manifests/apache/common.pp b/site-modules/profile/manifests/apache/common.pp new file mode 100644 index 00000000..6e3451aa --- /dev/null +++ b/site-modules/profile/manifests/apache/common.pp @@ -0,0 +1,5 @@ +class profile::apache::common { + include ::apache + include ::apache::mod::status + include ::profile::munin::plugins::apache +} diff --git a/site-modules/profile/manifests/apache/mod_proxy_fcgi.pp b/site-modules/profile/manifests/apache/mod_proxy_fcgi.pp new file mode 100644 index 00000000..2d2953b8 --- /dev/null +++ b/site-modules/profile/manifests/apache/mod_proxy_fcgi.pp @@ -0,0 +1,5 @@ +# Profile for apache mod proxy fcgi +class profile::apache::mod_proxy_fcgi { + include ::profile::apache::common + ::apache::mod {'proxy_fcgi':} +} diff --git a/site-modules/profile/manifests/apache/rewrite_domains.pp b/site-modules/profile/manifests/apache/rewrite_domains.pp new file mode 100644 index 00000000..992b3c95 --- /dev/null +++ b/site-modules/profile/manifests/apache/rewrite_domains.pp @@ -0,0 +1,46 @@ +# Simple apache domain rewriting +class profile::apache::rewrite_domains { + include ::profile::apache::common + + include ::profile::ssl + + $ssl_protocol = lookup('apache::ssl_protocol') + $ssl_honorcipherorder = lookup('apache::ssl_honorcipherorder') + $ssl_cipher = lookup('apache::ssl_cipher') + $hsts_header = lookup('apache::hsts_header') + + $rewrite_domains = lookup('apache::rewrite_domains', Hash, 'deep') + each($rewrite_domains) |$name, $data| { + $ssl_cert_name = $data['ssl_cert_name'] + + $ssl_cert = $::profile::ssl::certificate_paths[$ssl_cert_name] + $ssl_chain = $::profile::ssl::chain_paths[$ssl_cert_name] + $ssl_key = $::profile::ssl::private_key_paths[$ssl_cert_name] + + ::apache::vhost {"${name}_non-ssl": + servername => $name, + port => '80', + docroot => '/var/www', + redirect_status => 'permanent', + redirect_dest => "https://${name}/", + } + + + ::apache::vhost {"${name}_ssl": + servername => $name, + port => '443', + ssl => true, + ssl_protocol => $ssl_protocol, + ssl_honorcipherorder => $ssl_honorcipherorder, + ssl_cipher => $ssl_cipher, + ssl_cert => $ssl_cert, + ssl_chain => $ssl_chain, + ssl_key => $ssl_key, + headers => [$hsts_header], + docroot => '/var/www', + rewrites => [ + { rewrite_rule => $data['rewrites'], }, + ], + } + } +} diff --git a/site-modules/profile/manifests/apache/simple_server.pp b/site-modules/profile/manifests/apache/simple_server.pp new file mode 100644 index 00000000..3e52ea11 --- /dev/null +++ b/site-modules/profile/manifests/apache/simple_server.pp @@ -0,0 +1,3 @@ +class profile::apache::simple_server { + include ::profile::apache::common +} diff --git a/site-modules/profile/manifests/base.pp b/site-modules/profile/manifests/base.pp new file mode 100644 index 00000000..823a87e9 --- /dev/null +++ b/site-modules/profile/manifests/base.pp @@ -0,0 +1,140 @@ +# Base configuration for Software Heritage servers +class profile::base { + class { '::ntp': + servers => lookup('ntp::servers'), + } + + $relay_destinations = lookup('smtp::relay_destinations', Array, 'unique').reduce({}) |$ret, $value| { + $ret + {$value['destination'] => $value['route']} + } + + $virtual_aliases = lookup('smtp::virtual_aliases', Array, 'unique').reduce({}) |$ret, $value| { + $ret + {$value['destination'] => $value['alias']} + } + + class { '::postfix': + relayhost => lookup('smtp::relayhost'), + mydestination => lookup('smtp::mydestination', Array, 'unique'), + mynetworks => lookup('smtp::mynetworks', Array, 'unique'), + relay_destinations => $relay_destinations, + virtual_aliases => $virtual_aliases, + } + + exec {'newaliases': + path => ['/usr/bin', '/usr/sbin'], + refreshonly => true, + require => Package['postfix'], + } + + $mail_aliases = lookup('smtp::mail_aliases', Array, 'unique') + each($mail_aliases) |$alias| { + mailalias {$alias['user']: + ensure => present, + recipient => $alias['aliases'], + notify => Exec['newaliases'], + } + } + + class { '::locales': + default_locale => lookup('locales::default_locale'), + locales => lookup('locales::installed_locales'), + } + + $packages = lookup('packages', Array, 'unique') + + package { $packages: + ensure => present, + } + + $users = lookup('users', Hash, 'deep') + $groups = lookup('groups', Hash, 'deep') + + each($groups) |$name, $data| { + group { $name: + ensure => 'present', + gid => $data['gid'], + } + } + + each($users) |$name, $data| { + if $name == 'root' { + $home = '/root' + $mode = '0600' + } else { + $home = "/home/${name}" + $mode = '0644' + } + + user { $name: + ensure => 'present', + uid => $data['uid'], + comment => $data['full_name'], + shell => $data['shell'], + groups => $data['groups'], + password => $data['password'], + require => Group[$data['groups']], + } + + if ($data['shell'] == '/usr/bin/zsh') { + Package['zsh'] -> User[$name] + } + + if (has_key($groups, $name)) { + Group[$name] -> User[$name] + } + + file { $home: + ensure => 'directory', + mode => $mode, + owner => $name, + group => $name, + require => User[$name], + } + } + + class { '::sudo': + config_file_replace => false, + purge => false, + } + + ::sudo::conf { 'local-env': + ensure => present, + content => 'Defaults env_keep += "GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL"', + priority => 10, + } + + ::sudo::conf { 'local-deploy': + ensure => present, + content => '%swhdeploy ALL = NOPASSWD: /usr/local/sbin/swh-puppet-master-deploy, /usr/local/sbin/swh-puppet-test, /usr/local/sbin/swh-puppet-apply, /usr/bin/apt-get update', + priority => 20, + } + + class {'::timezone': + timezone => lookup('timezone'), + } + + $bind_autogenerate = lookup('bind::autogenerate') + $bind_key = lookup('bind::update_key') + + each($bind_autogenerate) |$net| { + $ipaddr = ip_for_network($net) + if $ipaddr { + $reverse = reverse_ipv4($ipaddr) + $fqdn = $::swh_hostname['internal_fqdn'] + + @@resource_record { "${fqdn}/A": + type => 'A', + record => $fqdn, + data => $ipaddr, + keyfile => "/etc/bind/keys/${bind_key}", + } + + @@resource_record { "${fqdn}/PTR": + type => 'PTR', + record => $reverse, + data => "${fqdn}.", + keyfile => "/etc/bind/keys/${bind_key}", + } + } + } +} diff --git a/site-modules/profile/manifests/bind_server.pp b/site-modules/profile/manifests/bind_server.pp new file mode 100644 index 00000000..e3e58227 --- /dev/null +++ b/site-modules/profile/manifests/bind_server.pp @@ -0,0 +1,83 @@ +class profile::bind_server { + + include ::profile::resolv_conf + + $forwarders = lookup('dns::forwarders') + $zones = lookup('bind::zones') + $default_zone_data = lookup('bind::zones::default_data') + $clients = lookup('bind::clients') + $resource_records = lookup('bind::resource_records') + $default_rr_data = lookup('bind::resource_records::default_data') + $update_key = lookup('bind::update_key') + $zone_names = keys($zones) + + class { '::bind': + forwarders => $forwarders, + dnssec => true, + } + + Service['bind'] -> File['/etc/resolv.conf'] + + bind::view { 'private': + recursion => true, + zones => $zone_names, + match_clients => $clients, + } + + bind::key { $update_key: + secret_bits => 512, + } + + each($zones) |$zone, $data| { + $merged_data = merge($default_zone_data, $data) + bind::zone { $zone: + zone_type => $merged_data['zone_type'], + domain => $merged_data['domain'], + dynamic => $merged_data['dynamic'], + masters => $merged_data['masters'], + transfer_source => $merged_data['transfer_source'], + allow_updates => union( + any2array($merged_data['allow_updates']), + ["key ${update_key}"], + ), + update_policies => $merged_data['update_policies'], + allow_transfers => $merged_data['allow_transfers'], + dnssec => $merged_data['dnssec'], + key_directory => $merged_data['key_directory'], + ns_notify => $merged_data['ns_notify'], + also_notify => $merged_data['also_notify'], + allow_notify => $merged_data['allow_notify'], + forwarders => $merged_data['forwarders'], + forward => $merged_data['forward'], + source => $merged_data['source'], + } + } + + each($resource_records) |$rr, $data| { + $merged_data = merge($default_rr_data, $data) + resource_record { $rr: + type => $merged_data['type'], + record => $merged_data['record'], + data => $merged_data['data'], + keyfile => "/etc/bind/keys/${update_key}", + } + + # Generate PTR record from A record + if $merged_data['type'] == 'A' { + $ptr = reverse_ipv4($merged_data['data']) + $ptr_domain = join(values_at(split($ptr, '[.]'), '1-5'), '.') + if member($zone_names, $ptr_domain) { + resource_record { "${rr}+PTR": + type => 'PTR', + record => $ptr, + data => "${merged_data['record']}.", + keyfile => "/etc/bind/keys/${update_key}", + } + } + } + } + + Resource_Record <<| |>> + + Bind::Zone <| |> -> Resource_Record <| |> +} diff --git a/site-modules/profile/manifests/ceph/base.pp b/site-modules/profile/manifests/ceph/base.pp new file mode 100644 index 00000000..0535388b --- /dev/null +++ b/site-modules/profile/manifests/ceph/base.pp @@ -0,0 +1,18 @@ +# Base configuration for Ceph +class profile::ceph::base { + $ceph_release = lookup('ceph::release') + + $ceph_fsid = lookup('ceph::fsid') + $ceph_mon_initial_members = join(lookup('ceph::mon_initial_members'), ',') + $ceph_mon_host = join(lookup('ceph::mon_host'), ',') + + class {'::ceph::repo': + release => $ceph_release, + } + + class {'::ceph': + fsid => $ceph_fsid, + mon_initial_members => $ceph_mon_initial_members, + mon_host => $ceph_mon_host, + } +} diff --git a/site-modules/profile/manifests/ceph/mon.pp b/site-modules/profile/manifests/ceph/mon.pp new file mode 100644 index 00000000..9c517dc7 --- /dev/null +++ b/site-modules/profile/manifests/ceph/mon.pp @@ -0,0 +1,30 @@ +# Ceph Monitor profile +class profile::ceph::mon { + include profile::ceph::base + + $mon_secret = lookup('ceph::secrets::mon') + $mgr_secret = lookup('ceph::secrets::mgr') + + $client_keys = lookup('ceph::keys') + + ::ceph::mon {$::hostname: + key => $mon_secret, + } + + ::ceph::mgr {$::hostname: + key => $mgr_secret, + inject_key => true, + } + + ::Ceph::Key { + inject => true, + inject_as_id => 'mon.', + inject_keyring => "/var/lib/ceph/mon/ceph-${::hostname}/keyring", + } + + each($client_keys) |$name, $data| { + ::ceph::key {"client.${name}": + * => $data, + } + } +} diff --git a/site-modules/profile/manifests/ceph/osd.pp b/site-modules/profile/manifests/ceph/osd.pp new file mode 100644 index 00000000..d9c0ecdc --- /dev/null +++ b/site-modules/profile/manifests/ceph/osd.pp @@ -0,0 +1,10 @@ +# Ceph OSD profile +class profile::ceph::osd { + include profile::ceph::base + + $bootstrap_osd_secret = lookup('ceph::secrets::bootstrap_osd') + ::ceph::key {'client.bootstrap-osd': + keyring_path => '/var/lib/ceph/bootstrap-osd/ceph.keyring', + secret => $bootstrap_osd_secret, + } +} diff --git a/site-modules/profile/manifests/dar/client.pp b/site-modules/profile/manifests/dar/client.pp new file mode 100644 index 00000000..484b7f14 --- /dev/null +++ b/site-modules/profile/manifests/dar/client.pp @@ -0,0 +1,68 @@ +class profile::dar::client { + include ::dar + + $dar_remote_hostname = $::swh_hostname['short'] + $dar_backup_name = $::hostname + + $hierahour = lookup('dar::cron::hour') + if $hierahour == 'fqdn_rand' { + $hour = fqdn_rand(24, 'backup_hour') + } else { + $hour = $hierahour + } + + $hieraminute = lookup('dar::cron::minute') + if $hieraminute == 'fqdn_rand' { + $minute = fqdn_rand(60, 'backup_minute') + } else { + $minute = $hieraminute + } + + $hieramonth = lookup('dar::cron::month') + if $hieramonth == 'fqdn_rand' { + $month = fqdn_rand(12, 'backup_month') + } else { + $month = $hieramonth + } + + $hieramonthday = lookup('dar::cron::monthday') + if $hieramonthday == 'fqdn_rand' { + $monthday = fqdn_rand(31, 'backup_monthday') + } else { + $monthday = $hieramonthday + } + + $hieraweekday = lookup('dar::cron::weekday') + if $hieraweekday == 'fqdn_rand' { + $weekday = fqdn_rand(31, 'backup_weekday') + } else { + $weekday = $hieraweekday + } + + dar::backup { $dar_backup_name: + backup_storage => lookup('dar::backup::storage'), + keep_backups => lookup('dar::backup::num_backups'), + backup_base => lookup('dar::backup::base'), + backup_selection => lookup('dar::backup::select'), + backup_exclusion => lookup('dar::backup::exclude', Array, 'unique'), + backup_options => lookup('dar::backup::options'), + hour => $hour, + minute => $minute, + month => $month, + monthday => $monthday, + weekday => $weekday, + } + + # Export a remote backup to the backup server + @@dar::remote_backup { "${dar_remote_hostname}.${dar_backup_name}": + remote_backup_storage => lookup('dar::backup::storage'), + remote_backup_host => $dar_remote_hostname, + remote_backup_name => $dar_backup_name, + local_backup_storage => lookup('dar_server::backup::storage'), + hour => lookup('dar_server::cron::hour'), + minute => lookup('dar_server::cron::minute'), + month => lookup('dar_server::cron::month'), + monthday => lookup('dar_server::cron::monthday'), + weekday => lookup('dar_server::cron::weekday'), + } +} diff --git a/site-modules/profile/manifests/dar/server.pp b/site-modules/profile/manifests/dar/server.pp new file mode 100644 index 00000000..8c240d3c --- /dev/null +++ b/site-modules/profile/manifests/dar/server.pp @@ -0,0 +1,3 @@ +class profile::dar::server { + include ::dar::backup_server +} diff --git a/site-modules/profile/manifests/debian_repository.pp b/site-modules/profile/manifests/debian_repository.pp new file mode 100644 index 00000000..a241d1c1 --- /dev/null +++ b/site-modules/profile/manifests/debian_repository.pp @@ -0,0 +1,118 @@ +# Debian repository configuration + +class profile::debian_repository { + $packages = ['reprepro'] + + package {$packages: + ensure => installed, + } + + $repository_basepath = lookup('debian_repository::basepath') + + $repository_vhost_name = lookup('debian_repository::vhost::name') + $repository_vhost_aliases = lookup('debian_repository::vhost::aliases') + $repository_vhost_docroot = lookup('debian_repository::vhost::docroot') + $repository_vhost_docroot_owner = lookup('debian_repository::vhost::docroot_owner') + $repository_vhost_docroot_group = lookup('debian_repository::vhost::docroot_group') + $repository_vhost_docroot_mode = lookup('debian_repository::vhost::docroot_mode') + $repository_vhost_ssl_protocol = lookup('debian_repository::vhost::ssl_protocol') + $repository_vhost_ssl_honorcipherorder = lookup('debian_repository::vhost::ssl_honorcipherorder') + $repository_vhost_ssl_cipher = lookup('debian_repository::vhost::ssl_cipher') + $repository_vhost_hsts_header = lookup('debian_repository::vhost::hsts_header') + + include ::profile::ssl + include ::profile::apache::common + + ::apache::vhost {"${repository_vhost_name}_non-ssl": + servername => $repository_vhost_name, + serveraliases => $repository_vhost_aliases, + port => '80', + docroot => $repository_vhost_docroot, + manage_docroot => false, # will be managed by the SSL resource + redirect_status => 'permanent', + redirect_dest => "https://${repository_vhost_name}/", + } + + $ssl_cert_name = 'star_softwareheritage_org' + $ssl_cert = $::profile::ssl::certificate_paths[$ssl_cert_name] + $ssl_chain = $::profile::ssl::chain_paths[$ssl_cert_name] + $ssl_key = $::profile::ssl::private_key_paths[$ssl_cert_name] + + ::apache::vhost {"${repository_vhost_name}_ssl": + servername => $repository_vhost_name, + port => '443', + ssl => true, + ssl_protocol => $repository_vhost_ssl_protocol, + ssl_honorcipherorder => $repository_vhost_ssl_honorcipherorder, + ssl_cipher => $repository_vhost_ssl_cipher, + ssl_cert => $ssl_cert, + ssl_chain => $ssl_chain, + ssl_key => $ssl_key, + headers => [$repository_vhost_hsts_header], + docroot => $repository_vhost_docroot, + docroot_owner => $repository_vhost_docroot_owner, + docroot_group => $repository_vhost_docroot_group, + docroot_mode => $repository_vhost_docroot_mode, + directories => [ + { + path => $repository_vhost_docroot, + require => 'all granted', + options => ['Indexes', 'FollowSymLinks', 'MultiViews'], + }, + ], + require => [ + File[$ssl_cert], + File[$ssl_chain], + File[$ssl_key], + ], + } + + $icinga_checks_file = '/etc/icinga2/conf.d/exported-checks.conf' + + @@::icinga2::object::service {"debian repository http redirect on ${::fqdn}": + service_name => 'debian repository http redirect', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $repository_vhost_name, + http_vhost => $repository_vhost_name, + http_uri => '/', + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + @@::icinga2::object::service {"debian repository https on ${::fqdn}": + service_name => 'debian repository https', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $repository_vhost_name, + http_vhost => $repository_vhost_name, + http_ssl => true, + http_sni => true, + http_uri => '/', + http_onredirect => sticky + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + @@::icinga2::object::service {"debian repository https certificate ${::fqdn}": + service_name => 'debian repository https certificate', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $repository_vhost_name, + http_vhost => $repository_vhost_name, + http_ssl => true, + http_sni => true, + http_certificate => 60, + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } +} diff --git a/site-modules/profile/manifests/desktop.pp b/site-modules/profile/manifests/desktop.pp new file mode 100644 index 00000000..e85925a7 --- /dev/null +++ b/site-modules/profile/manifests/desktop.pp @@ -0,0 +1,9 @@ +class profile::desktop { + $packages = lookup('packages::desktop', Array, 'unique') + + package { $packages: + ensure => present, + } + + include ::profile::desktop::printers +} diff --git a/site-modules/profile/manifests/desktop/printers.pp b/site-modules/profile/manifests/desktop/printers.pp new file mode 100644 index 00000000..12ad0ae0 --- /dev/null +++ b/site-modules/profile/manifests/desktop/printers.pp @@ -0,0 +1,87 @@ +class profile::desktop::printers { + $printers = lookup('desktop::printers', Hash, 'deep') + $default_printer = lookup('desktop::printers::default') + $cups_usernames = lookup('desktop::printers::cups_usernames', Hash, 'deep') + + $ppd_dir = lookup('desktop::printers::ppd_dir') + $ppd_file = "${ppd_dir}/MFP.ppd" + $ppd_auth_filter = "${ppd_dir}/MFP_auth_filter" + + class {'::cups': + default_printer => $default_printer, + } + + each($printers) |$printer, $params| { + printer {$printer: + ensure => present, + uri => $params['uri'], + description => $params['description'], + ppd => $params['ppd'], + location => $params['location'], + ppd_options => $params['ppd_options'], + shared => false, + require => File[$params['ppd']], + } + } + + Printer[$default_printer] -> Exec['default_printer'] + + each ($cups_usernames) |$user, $cups_user| { + file {"/home/${user}/.cups": + ensure => directory, + owner => $user, + group => $user, + mode => '0640', + } + + file {"/home/${user}/.cups/client.conf": + ensure => present, + owner => $user, + group => $user, + mode => '0640', + } + + file_line {"cups_username_${user}": + path => "/home/${user}/.cups/client.conf", + line => "User ${cups_user}", + match => '^User ', + } + } + + file {$ppd_dir: + ensure => directory, + owner => root, + group => root, + mode => '0644', + require => Package['cups'], + } + + # Template uses $ppd_auth_filter + file {"${ppd_dir}/MFP_Paris.ppd": + ensure => present, + owner => root, + group => root, + mode => '0644', + content => template('profile/desktop/printers/MFP_Paris.ppd.erb'), + require => [ + File[$ppd_dir], + File[$ppd_auth_filter], + ], + } + + file {$ppd_auth_filter: + ensure => present, + owner => root, + group => root, + mode => '0755', + source => 'puppet:///modules/profile/desktop/printers/MFP_auth_filter', + require => [ + File[$ppd_dir], + ], + } + + service {'cups-browsed': + ensure => stopped, + enable => false, + } +} diff --git a/site-modules/profile/manifests/devel.pp b/site-modules/profile/manifests/devel.pp new file mode 100644 index 00000000..2bf0d1e7 --- /dev/null +++ b/site-modules/profile/manifests/devel.pp @@ -0,0 +1,13 @@ +# profile for the workstation of a Software Heritage developer +class profile::devel { + $packages = lookup('packages::devel', Array, 'unique') + + package { $packages: + ensure => present, + } + + include ::profile::devel::debian + include ::profile::devel::postgres + include ::profile::devel::python + include ::profile::devel::broker +} diff --git a/site-modules/profile/manifests/devel/broker.pp b/site-modules/profile/manifests/devel/broker.pp new file mode 100644 index 00000000..0fa9b273 --- /dev/null +++ b/site-modules/profile/manifests/devel/broker.pp @@ -0,0 +1,7 @@ +class profile::devel::broker { + $packages = lookup('packages::devel::broker', Array, 'unique') + + package { $packages: + ensure => present, + } +} diff --git a/site-modules/profile/manifests/devel/debian.pp b/site-modules/profile/manifests/devel/debian.pp new file mode 100644 index 00000000..d9b4fd92 --- /dev/null +++ b/site-modules/profile/manifests/devel/debian.pp @@ -0,0 +1,7 @@ +class profile::devel::debian { + $packages = lookup('packages::devel::debian', Array, 'unique') + + package { $packages: + ensure => present, + } +} diff --git a/site-modules/profile/manifests/devel/postgres.pp b/site-modules/profile/manifests/devel/postgres.pp new file mode 100644 index 00000000..cc7bac4e --- /dev/null +++ b/site-modules/profile/manifests/devel/postgres.pp @@ -0,0 +1,13 @@ +class profile::devel::postgres { + $packages = lookup('packages::devel::postgres', Array, 'unique') + + package { $packages: + ensure => present, + } + + file { '/etc/postgresql-common/pg_service.conf': + ensure => file, + content => template('profile/postgres/pg_service.conf.erb'), + require => Package[$packages], + } +} diff --git a/site-modules/profile/manifests/devel/python.pp b/site-modules/profile/manifests/devel/python.pp new file mode 100644 index 00000000..f767e3e5 --- /dev/null +++ b/site-modules/profile/manifests/devel/python.pp @@ -0,0 +1,7 @@ +class profile::devel::python { + $packages = lookup('packages::devel::python', Array, 'unique') + + package { $packages: + ensure => present, + } +} diff --git a/site-modules/profile/manifests/docker.pp b/site-modules/profile/manifests/docker.pp new file mode 100644 index 00000000..af34256e --- /dev/null +++ b/site-modules/profile/manifests/docker.pp @@ -0,0 +1,27 @@ +class profile::docker { + $mirror = lookup('docker::apt_config::mirror') + $keyid = lookup('docker::apt_config::keyid') + $key = lookup('docker::apt_config::key') + + apt::source {'docker': + location => $mirror, + release => $facts['os']['distro']['codename'], + repos => 'stable', + architecture => 'amd64', + key => { + id => $keyid, + content => $key, + }, + include => { + src => false, + deb => true, + } + } + -> package {'docker-ce': + ensure => present, + } + -> service {'docker': + ensure => running, + enable => true, + } +} diff --git a/site-modules/profile/manifests/docs_web.pp b/site-modules/profile/manifests/docs_web.pp new file mode 100644 index 00000000..b931c78a --- /dev/null +++ b/site-modules/profile/manifests/docs_web.pp @@ -0,0 +1,106 @@ +# Deployment of web-facing static documentation +class profile::docs_web { + + $docs_basepath = lookup('docs::basepath') + + $docs_vhost_name = lookup('docs::vhost::name') + $docs_vhost_docroot = lookup('docs::vhost::docroot') + $docs_vhost_docroot_group = lookup('docs::vhost::docroot_group') + $docs_vhost_docroot_mode = lookup('docs::vhost::docroot_mode') + $docs_vhost_ssl_protocol = lookup('docs::vhost::ssl_protocol') + $docs_vhost_ssl_honorcipherorder = lookup('docs::vhost::ssl_honorcipherorder') + $docs_vhost_ssl_cipher = lookup('docs::vhost::ssl_cipher') + $docs_vhost_hsts_header = lookup('docs::vhost::hsts_header') + + include ::profile::ssl + include ::profile::apache::common + + ::apache::vhost {"${docs_vhost_name}_non-ssl": + servername => $docs_vhost_name, + port => '80', + docroot => $docs_vhost_docroot, + manage_docroot => false, # will be managed by the SSL resource + redirect_status => 'permanent', + redirect_dest => "https://${docs_vhost_name}/", + } + + $ssl_cert_name = 'star_softwareheritage_org' + $ssl_cert = $::profile::ssl::certificate_paths[$ssl_cert_name] + $ssl_chain = $::profile::ssl::chain_paths[$ssl_cert_name] + $ssl_key = $::profile::ssl::private_key_paths[$ssl_cert_name] + + ::apache::vhost {"${docs_vhost_name}_ssl": + servername => $docs_vhost_name, + port => '443', + ssl => true, + ssl_protocol => $docs_vhost_ssl_protocol, + ssl_honorcipherorder => $docs_vhost_ssl_honorcipherorder, + ssl_cipher => $docs_vhost_ssl_cipher, + ssl_cert => $ssl_cert, + ssl_chain => $ssl_chain, + ssl_key => $ssl_key, + headers => [$docs_vhost_hsts_header], + docroot => $docs_vhost_docroot, + docroot_group => $docs_vhost_docroot_group, + docroot_mode => $docs_vhost_docroot_mode, + directories => [{ + 'path' => $docs_vhost_docroot, + 'require' => 'all granted', + 'options' => ['Indexes', 'FollowSymLinks', 'MultiViews'], + }], + require => [ + File[$ssl_cert], + File[$ssl_chain], + File[$ssl_key], + ], + } + + $icinga_checks_file = '/etc/icinga2/conf.d/exported-checks.conf' + + @@::icinga2::object::service {"docs http redirect on ${::fqdn}": + service_name => 'docs http redirect', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $docs_vhost_name, + http_vhost => $docs_vhost_name, + http_uri => '/', + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + @@::icinga2::object::service {"docs https on ${::fqdn}": + service_name => 'docs https', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $docs_vhost_name, + http_vhost => $docs_vhost_name, + http_ssl => true, + http_sni => true, + http_uri => '/', + http_onredirect => sticky + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + @@::icinga2::object::service {"docs https certificate ${::fqdn}": + service_name => 'docs https certificate', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $docs_vhost_name, + http_vhost => $docs_vhost_name, + http_ssl => true, + http_sni => true, + http_certificate => 60, + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } +} diff --git a/site-modules/profile/manifests/elasticsearch.pp b/site-modules/profile/manifests/elasticsearch.pp new file mode 100644 index 00000000..c696964d --- /dev/null +++ b/site-modules/profile/manifests/elasticsearch.pp @@ -0,0 +1,47 @@ +# Elasticsearch cluster node profile + +class profile::elasticsearch { + + user { 'elasticsearch': + ensure => 'present', + uid => '114', + gid => '119', + home => '/home/elasticsearch', + shell => '/bin/false', + } + + file { '/srv/elasticsearch': + ensure => 'directory', + owner => 'elasticsearch', + mode => '755', + } + + package { 'openjdk-8-jre-headless': + ensure => 'present', + } + + # Elasticsearch official package installation instructions: + # https://www.elastic.co/guide/en/elasticsearch/reference/current/deb.html + $keyid = lookup('elastic::apt_config::keyid') + $key = lookup('elastic::apt_config::key') + + apt::source { 'elastic-6.x': + location => 'https://artifacts.elastic.co/packages/6.x/apt', + release => 'stable', + repos => 'main', + key => { + id => $keyid, + content => $key, + }, + } + + package { 'elasticsearch': + ensure => 'present', + } + + service { 'elasticsearch': + ensure => running, + enable => true, + } + +} diff --git a/site-modules/profile/manifests/grafana.pp b/site-modules/profile/manifests/grafana.pp new file mode 100644 index 00000000..7aca07ec --- /dev/null +++ b/site-modules/profile/manifests/grafana.pp @@ -0,0 +1,31 @@ +class profile::grafana { + $db = lookup('grafana::db::database') + $db_username = lookup('grafana::db::username') + $db_password = lookup('grafana::db::password') + + $config = lookup('grafana::config') + + include ::postgresql::server + + ::postgresql::server::db {$db: + user => $db_username, + password => postgresql_password($db_username, $db_password), + } + + class {'::grafana': + install_method => 'repo', + version => 'latest', + cfg => $config + { + database => { + type => 'postgres', + host => '127.0.0.1:5432', + name => $db, + user => $db_username, + password => $db_password + } + } + } + + contain profile::grafana::vhost + contain profile::grafana::objects +} diff --git a/site-modules/profile/manifests/grafana/objects.pp b/site-modules/profile/manifests/grafana/objects.pp new file mode 100644 index 00000000..3c343ebb --- /dev/null +++ b/site-modules/profile/manifests/grafana/objects.pp @@ -0,0 +1,44 @@ +# Creation of grafana objects + +class profile::grafana::objects { + $grafana_vhost = lookup('grafana::vhost::name') + $grafana_url = "https://${grafana_vhost}" + $grafana_user = 'admin' + $passwords = lookup('grafana::passwords') + $grafana_password = $passwords[$grafana_user] + + $orgs = lookup('grafana::objects::organizations') + + each($orgs) |$org| { + grafana_organization {$org['name']: + grafana_url => $grafana_url, + grafana_user => $grafana_user, + grafana_password => $grafana_password, + * => $org - 'name', + } + } + + $users = lookup('grafana::objects::users') + + each($users) |$user| { + $password = $passwords[$user['username']] + grafana_user {$user['username']: + grafana_url => $grafana_url, + grafana_user => $grafana_user, + grafana_password => $grafana_password, + password => $password, + * => $user - 'username', + } + } + + $datasources = lookup('grafana::objects::datasources') + + each($datasources) |$datasource| { + grafana_datasource {$datasource['name']: + grafana_url => $grafana_url, + grafana_user => $grafana_user, + grafana_password => $grafana_password, + * => $datasource - 'name', + } + } +} diff --git a/site-modules/profile/manifests/grafana/vhost.pp b/site-modules/profile/manifests/grafana/vhost.pp new file mode 100644 index 00000000..dc6e123b --- /dev/null +++ b/site-modules/profile/manifests/grafana/vhost.pp @@ -0,0 +1,104 @@ +# Apache virtual host for grafana + +class profile::grafana::vhost { + include ::profile::ssl + include ::profile::apache::common + include ::apache::mod::proxy + + $grafana_vhost_name = lookup('grafana::vhost::name') + $grafana_vhost_docroot = '/var/www/html' + $grafana_vhost_ssl_protocol = lookup('grafana::vhost::ssl_protocol') + $grafana_vhost_ssl_honorcipherorder = lookup('grafana::vhost::ssl_honorcipherorder') + $grafana_vhost_ssl_cipher = lookup('grafana::vhost::ssl_cipher') + $grafana_vhost_hsts_header = lookup('grafana::vhost::hsts_header') + $grafana_upstream_port = lookup('grafana::backend::port') + $grafana_backend_url = "http://127.0.0.1:${grafana_upstream_port}/" + + ::apache::vhost {"${grafana_vhost_name}_non-ssl": + servername => $grafana_vhost_name, + port => '80', + docroot => $grafana_vhost_docroot, + manage_docroot => false, # will be managed by the SSL resource + redirect_status => 'permanent', + redirect_dest => "https://${grafana_vhost_name}/", + } + + $ssl_cert_name = 'star_softwareheritage_org' + $ssl_cert = $::profile::ssl::certificate_paths[$ssl_cert_name] + $ssl_chain = $::profile::ssl::chain_paths[$ssl_cert_name] + $ssl_key = $::profile::ssl::private_key_paths[$ssl_cert_name] + + ::apache::vhost {"${grafana_vhost_name}_ssl": + servername => $grafana_vhost_name, + port => '443', + ssl => true, + ssl_protocol => $grafana_vhost_ssl_protocol, + ssl_honorcipherorder => $grafana_vhost_ssl_honorcipherorder, + ssl_cipher => $grafana_vhost_ssl_cipher, + ssl_cert => $ssl_cert, + ssl_chain => $ssl_chain, + ssl_key => $ssl_key, + headers => [$grafana_vhost_hsts_header], + docroot => $grafana_vhost_docroot, + manage_docroot => false, + proxy_pass => [ + { path => '/', + url => $grafana_backend_url, + }, + ], + require => [ + File[$ssl_cert], + File[$ssl_chain], + File[$ssl_key], + ], + } + + $icinga_checks_file = '/etc/icinga2/conf.d/exported-checks.conf' + + @@::icinga2::object::service {"grafana http redirect on ${::fqdn}": + service_name => 'grafana http redirect', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $grafana_vhost_name, + http_vhost => $grafana_vhost_name, + http_uri => '/', + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + @@::icinga2::object::service {"grafana https on ${::fqdn}": + service_name => 'grafana https', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $grafana_vhost_name, + http_vhost => $grafana_vhost_name, + http_ssl => true, + http_sni => true, + http_uri => '/login', + http_string => 'Grafana', + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + @@::icinga2::object::service {"grafana https certificate ${::fqdn}": + service_name => 'grafana https certificate', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $grafana_vhost_name, + http_vhost => $grafana_vhost_name, + http_ssl => true, + http_sni => true, + http_certificate => 60, + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } +} diff --git a/site-modules/profile/manifests/hitch.pp b/site-modules/profile/manifests/hitch.pp new file mode 100644 index 00000000..f9e3cd47 --- /dev/null +++ b/site-modules/profile/manifests/hitch.pp @@ -0,0 +1,46 @@ +# Support for hitch TLS termination proxy +class profile::hitch { + $frontend = lookup('hitch::frontend') + $proxy_support = lookup('hitch::proxy_support') + $http2_support = lookup('hitch::http2_support') + + $ocsp_dir = '/var/lib/hitch' + + if $proxy_support { + $varnish_proxy_port = lookup('varnish::proxy_port') + $backend = "[::1]:${varnish_proxy_port}" + $write_proxy_v2 = 'on' + } else { + $apache_http_port = lookup('apache::http_port') + $backend = "[::1]:${apache_http_port}" + $write_proxy_v2 = 'off' + } + + if $http2_support { + $alpn_protos = 'h2,http/1.1' + } else { + $alpn_protos = undef + } + + class {'::hitch': + frontend => $frontend, + backend => $backend, + write_proxy_v2 => $write_proxy_v2, + alpn_protos => $alpn_protos, + require => File[$ocsp_dir], + } + + file {$ocsp_dir: + ensure => directory, + mode => '0700', + owner => $::hitch::user, + group => $::hitch::group, + notify => Service[$::hitch::service_name], + } + + # Provide virtual resources for each possible hitch TLS certificate + # Users can realize the resource using + # realize(::Profile::Hitch::Ssl_Cert[$cert_name]) + $ssl_certs = keys(lookup('ssl')) + @::profile::hitch::ssl_cert {$ssl_certs:} +} diff --git a/site-modules/profile/manifests/hitch/ssl_cert.pp b/site-modules/profile/manifests/hitch/ssl_cert.pp new file mode 100644 index 00000000..ac29fd2b --- /dev/null +++ b/site-modules/profile/manifests/hitch/ssl_cert.pp @@ -0,0 +1,16 @@ +# Configure hitch to support a given TLS cert +define profile::hitch::ssl_cert ( + String $ssl_cert_name = $title, +){ + include ::profile::ssl + + $ssl_cert = $::profile::ssl::certificate_paths[$ssl_cert_name] + $ssl_chain = $::profile::ssl::chain_paths[$ssl_cert_name] + $ssl_key = $::profile::ssl::private_key_paths[$ssl_cert_name] + + ::hitch::domain {$ssl_cert_name: + key_source => $ssl_key, + cert_source => $ssl_cert, + cacert_source => $ssl_chain, + } +} diff --git a/site-modules/profile/manifests/icinga2.pp b/site-modules/profile/manifests/icinga2.pp new file mode 100644 index 00000000..6f2bc5a2 --- /dev/null +++ b/site-modules/profile/manifests/icinga2.pp @@ -0,0 +1,12 @@ +# Icinga2 configuration +class profile::icinga2 { + $icinga2_role = lookup('icinga2::role') + + include profile::icinga2::apt_config + + case $icinga2_role { + 'agent': { include profile::icinga2::agent } + 'master': { include profile::icinga2::master } + default: { fail("Unknown icinga2::role: ${icinga2_role}") } + } +} diff --git a/site-modules/profile/manifests/icinga2/agent.pp b/site-modules/profile/manifests/icinga2/agent.pp new file mode 100644 index 00000000..f4143998 --- /dev/null +++ b/site-modules/profile/manifests/icinga2/agent.pp @@ -0,0 +1,77 @@ +# Icinga2 agent configuration +class profile::icinga2::agent { + $features = lookup('icinga2::features') + $icinga2_network = lookup('icinga2::network') + $hiera_host_vars = lookup('icinga2::host::vars', Hash, 'deep') + + $parent_zone = lookup('icinga2::parent_zone') + $parent_endpoints = lookup('icinga2::parent_endpoints') + + include profile::icinga2::objects::agent_checks + + $check_mounts = $::mounts.filter |$mount| { + $mount !~ /^\/srv\/containers/ + } + + $local_host_vars = { + disks => hash(flatten( + $check_mounts.map |$mount| { + ["disk ${mount}", {disk_partitions => $mount}] + }, + )), + plugins => keys($profile::icinga2::objects::agent_checks::plugins), + } + + class {'::icinga2': + confd => true, + features => $features, + } + + class { '::icinga2::feature::api': + accept_config => true, + accept_commands => true, + zones => { + 'ZoneName' => { + endpoints => ['NodeName'], + parent => $parent_zone, + }, + }, + } + + create_resources('::icinga2::object::endpoint', $parent_endpoints) + ::icinga2::object::zone {$parent_zone: + endpoints => keys($parent_endpoints), + } + + @@::icinga2::object::endpoint {$::fqdn: + target => "/etc/icinga2/zones.d/${parent_zone}/${::fqdn}.conf", + } + + @@::icinga2::object::zone {$::fqdn: + endpoints => [$::fqdn], + parent => $parent_zone, + target => "/etc/icinga2/zones.d/${parent_zone}/${::fqdn}.conf", + } + + @@::icinga2::object::host {$::fqdn: + address => ip_for_network($icinga2_network), + display_name => $::fqdn, + check_command => 'hostalive', + vars => deep_merge($local_host_vars, $hiera_host_vars), + target => "/etc/icinga2/zones.d/${parent_zone}/${::fqdn}.conf", + } + + icinga2::object::zone { 'global-templates': + global => true, + } + + file {['/etc/icinga2/conf.d']: + ensure => directory, + owner => 'nagios', + group => 'nagios', + mode => '0755', + purge => true, + recurse => true, + tag => 'icinga2::config::file', + } +} diff --git a/site-modules/profile/manifests/icinga2/apt_config.pp b/site-modules/profile/manifests/icinga2/apt_config.pp new file mode 100644 index 00000000..580c3fe1 --- /dev/null +++ b/site-modules/profile/manifests/icinga2/apt_config.pp @@ -0,0 +1,20 @@ +# Icinga2 APT configuration +class profile::icinga2::apt_config { + $mirror = lookup('icinga2::apt_config::mirror') + $keyid = lookup('icinga2::apt_config::keyid') + $key = lookup('icinga2::apt_config::key') + + apt::source { 'icinga-stable-release': + location => $mirror, + release => "icinga-${::lsbdistcodename}", + repos => 'main', + key => { + id => $keyid, + content => $key, + }, + include => { + src => false, + deb => true, + }, + } +} diff --git a/site-modules/profile/manifests/icinga2/icingaweb2.pp b/site-modules/profile/manifests/icinga2/icingaweb2.pp new file mode 100644 index 00000000..39d9f316 --- /dev/null +++ b/site-modules/profile/manifests/icinga2/icingaweb2.pp @@ -0,0 +1,62 @@ +# Icinga web 2 configuration +class profile::icinga2::icingaweb2 { + $icinga2_db_username = lookup('icinga2::master::db::username') + $icinga2_db_password = lookup('icinga2::master::db::password') + $icinga2_db_database = lookup('icinga2::master::db::database') + + $icingaweb2_db_username = lookup('icinga2::icingaweb2::db::username') + $icingaweb2_db_password = lookup('icinga2::icingaweb2::db::password') + $icingaweb2_db_database = lookup('icinga2::icingaweb2::db::database') + $icingaweb2_protected_customvars = lookup('icinga2::icingaweb2::protected_customvars') + + include profile::icinga2::apt_config + include profile::icinga2::icingaweb2::vhost + + class {'::icingaweb2': + manage_repo => false, + manage_package => true, + import_schema => true, + db_type => 'pgsql', + db_host => 'localhost', + db_port => 5432, + db_username => $icingaweb2_db_username, + db_password => $icingaweb2_db_password, + require => Postgresql::Server::Db[$icingaweb2_db_database], + } + + # Icingaweb2 modules + + ::postgresql::server::db {$icingaweb2_db_database: + user => $icingaweb2_db_username, + password => postgresql_password($icingaweb2_db_username, $icingaweb2_db_password), + } + + class {'::icingaweb2::module::monitoring': + ido_type => 'pgsql', + ido_host => 'localhost', + ido_port => 5432, + ido_db_name => $icinga2_db_database, + ido_db_username => $icinga2_db_username, + ido_db_password => $icinga2_db_password, + protected_customvars => join($icingaweb2_protected_customvars, ', '), + commandtransports => { + icinga2 => { + transport => 'local', + path => '/var/run/icinga2/cmd/icinga2.cmd', + } + } + } + + include ::icingaweb2::module::doc + + # Icingaweb2 permissions + ::icingaweb2::config::role {'guest': + users => 'guest', + permissions => 'module/monitoring', + } + + ::icingaweb2::config::role {'icinga': + users => 'icinga', + permissions => '*', + } +} diff --git a/site-modules/profile/manifests/icinga2/icingaweb2/vhost.pp b/site-modules/profile/manifests/icinga2/icingaweb2/vhost.pp new file mode 100644 index 00000000..816ef53c --- /dev/null +++ b/site-modules/profile/manifests/icinga2/icingaweb2/vhost.pp @@ -0,0 +1,122 @@ +# Apache virtual host for icingaweb2 + +class profile::icinga2::icingaweb2::vhost { + include ::profile::ssl + include ::profile::apache::common + include ::apache::mod::php + + $icingaweb2_vhost_name = lookup('icinga2::icingaweb2::vhost::name') + $icingaweb2_vhost_aliases = lookup('icinga2::icingaweb2::vhost::aliases') + $icingaweb2_vhost_docroot = '/usr/share/icingaweb2/public' + $icingaweb2_vhost_ssl_protocol = lookup('icinga2::icingaweb2::vhost::ssl_protocol') + $icingaweb2_vhost_ssl_honorcipherorder = lookup('icinga2::icingaweb2::vhost::ssl_honorcipherorder') + $icingaweb2_vhost_ssl_cipher = lookup('icinga2::icingaweb2::vhost::ssl_cipher') + $icingaweb2_vhost_hsts_header = lookup('icinga2::icingaweb2::vhost::hsts_header') + + ::apache::vhost {"${icingaweb2_vhost_name}_non-ssl": + servername => $icingaweb2_vhost_name, + serveraliases => $icingaweb2_vhost_aliases, + port => '80', + docroot => $icingaweb2_vhost_docroot, + manage_docroot => false, # will be managed by the SSL resource + redirect_status => 'permanent', + redirect_dest => "https://${icingaweb2_vhost_name}/", + } + + $ssl_cert_name = 'star_softwareheritage_org' + $ssl_cert = $::profile::ssl::certificate_paths[$ssl_cert_name] + $ssl_chain = $::profile::ssl::chain_paths[$ssl_cert_name] + $ssl_key = $::profile::ssl::private_key_paths[$ssl_cert_name] + + ::apache::vhost {"${icingaweb2_vhost_name}_ssl": + servername => $icingaweb2_vhost_name, + port => '443', + ssl => true, + ssl_protocol => $icingaweb2_vhost_ssl_protocol, + ssl_honorcipherorder => $icingaweb2_vhost_ssl_honorcipherorder, + ssl_cipher => $icingaweb2_vhost_ssl_cipher, + ssl_cert => $ssl_cert, + ssl_chain => $ssl_chain, + ssl_key => $ssl_key, + headers => [$icingaweb2_vhost_hsts_header], + docroot => $icingaweb2_vhost_docroot, + manage_docroot => false, + directories => [ + { + path => $icingaweb2_vhost_docroot, + require => 'all granted', + options => ['SymlinksIfOwnerMatch'], + setenv => ['ICINGAWEB_CONFIGDIR "/etc/icingaweb2"'], + allow_override => ['None'], + rewrites => [ + { + rewrite_cond => [ + '%{REQUEST_FILENAME} -s [OR]', + '%{REQUEST_FILENAME} -l [OR]', + '%{REQUEST_FILENAME} -d', + ], + rewrite_rule => '^.*$ - [NC,L]', + }, + { + rewrite_rule => '^.*$ index.php [NC,L]', + } + ], + }, + ], + require => [ + File[$ssl_cert], + File[$ssl_chain], + File[$ssl_key], + ], + } + + $icinga_checks_file = '/etc/icinga2/conf.d/exported-checks.conf' + + @@::icinga2::object::service {"icingaweb2 http redirect on ${::fqdn}": + service_name => 'icingaweb2 http redirect', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $icingaweb2_vhost_name, + http_vhost => $icingaweb2_vhost_name, + http_uri => '/', + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + @@::icinga2::object::service {"icingaweb2 https on ${::fqdn}": + service_name => 'icingaweb2 https', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $icingaweb2_vhost_name, + http_vhost => $icingaweb2_vhost_name, + http_ssl => true, + http_sni => true, + http_uri => '/authentication/login', + http_header => ['Cookie: _chc=1'], + http_string => 'Icinga Web 2 Login', + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + @@::icinga2::object::service {"icingaweb2 https certificate ${::fqdn}": + service_name => 'icingaweb2 https certificate', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $icingaweb2_vhost_name, + http_vhost => $icingaweb2_vhost_name, + http_ssl => true, + http_sni => true, + http_certificate => 60, + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } +} diff --git a/site-modules/profile/manifests/icinga2/master.pp b/site-modules/profile/manifests/icinga2/master.pp new file mode 100644 index 00000000..acb6f369 --- /dev/null +++ b/site-modules/profile/manifests/icinga2/master.pp @@ -0,0 +1,101 @@ +# An icinga master host +class profile::icinga2::master { + $zonename = lookup('icinga2::master::zonename') + $features = lookup('icinga2::features') + $icinga2_network = lookup('icinga2::network') + + $hiera_host_vars = lookup('icinga2::host::vars', Hash, 'deep') + + $icinga2_db_username = lookup('icinga2::master::db::username') + $icinga2_db_password = lookup('icinga2::master::db::password') + $icinga2_db_database = lookup('icinga2::master::db::database') + + include profile::icinga2::objects + include profile::icinga2::objects::agent_checks + + $local_host_vars = { + disks => hash(flatten( + $::mounts.map |$mount| { + ["disk ${mount}", {disk_partitions => $mount}] + }, + )), + plugins => keys($profile::icinga2::objects::agent_checks::plugins), + } + + include ::postgresql::server + + ::postgresql::server::db {$icinga2_db_database: + user => $icinga2_db_username, + password => postgresql_password($icinga2_db_username, $icinga2_db_password) + } + + class {'::icinga2': + confd => true, + features => $features, + constants => { + 'ZoneName' => $zonename, + }, + } + + class { '::icinga2::feature::api': + accept_commands => true, + zones => {}, + endpoints => {}, + } + + class { '::icinga2::feature::idopgsql': + user => $icinga2_db_username, + password => $icinga2_db_password, + database => $icinga2_db_database, + import_schema => true, + require => Postgresql::Server::Db[$icinga2_db_database], + } + + @@::icinga2::object::endpoint {$::fqdn: + target => "/etc/icinga2/zones.d/${zonename}/${::fqdn}.conf", + } + + @@::icinga2::object::zone {$zonename: + endpoints => [$::fqdn], + target => "/etc/icinga2/zones.d/${zonename}/${::fqdn}.conf", + } + + @@::icinga2::object::host {$::fqdn: + address => ip_for_network($icinga2_network), + display_name => $::fqdn, + check_command => 'hostalive', + vars => deep_merge($local_host_vars, $hiera_host_vars), + target => "/etc/icinga2/zones.d/${zonename}/${::fqdn}.conf", + } + + ::Icinga2::Object::Host <<| |>> + ::Icinga2::Object::Endpoint <<| |>> + ::Icinga2::Object::Zone <<| |>> + + ::icinga2::object::zone { 'global-templates': + global => true, + } + + file {[ + '/etc/icinga2/zones.d/global-templates', + "/etc/icinga2/zones.d/${zonename}", + ]: + ensure => directory, + owner => 'nagios', + group => 'nagios', + mode => '0755', + tag => 'icinga2::config::file', + recurse => true, + purge => true, + } + + file {'/etc/icinga2/conf.d': + ensure => directory, + owner => 'nagios', + group => 'nagios', + mode => '0755', + purge => true, + recurse => true, + tag => 'icinga2::config::file', + } +} diff --git a/site-modules/profile/manifests/icinga2/objects.pp b/site-modules/profile/manifests/icinga2/objects.pp new file mode 100644 index 00000000..f1c89d20 --- /dev/null +++ b/site-modules/profile/manifests/icinga2/objects.pp @@ -0,0 +1,17 @@ +# Icinga2 object definitions +class profile::icinga2::objects { + include profile::icinga2::objects::templates + include profile::icinga2::objects::commands + include profile::icinga2::objects::users + include profile::icinga2::objects::notifications + include profile::icinga2::objects::timeperiods + include profile::icinga2::objects::apiusers + + include profile::icinga2::objects::common_checks + include profile::icinga2::objects::static_checks + include profile::icinga2::objects::agent_checks + include profile::icinga2::objects::exported_checks + + include profile::icinga2::plugins::rabbitmq + +} diff --git a/site-modules/profile/manifests/icinga2/objects/agent_checks.pp b/site-modules/profile/manifests/icinga2/objects/agent_checks.pp new file mode 100644 index 00000000..a39a263d --- /dev/null +++ b/site-modules/profile/manifests/icinga2/objects/agent_checks.pp @@ -0,0 +1,89 @@ +# Checks that need to be supported on icinga2 agents +class profile::icinga2::objects::agent_checks { + $plugins = { + 'check_journal' => { + arguments => { + '-f' => { + 'value' => '$journal_cursor_file$', + 'set_if' => '$journal_cursor_file$', + }, + '-w' => '$journal_lag_warn$', + '-c' => '$journal_lag_crit$', + '-wn' => { + 'value' => '$journal_lag_entries_warn$', + 'set_if' => '$journal_lag_entries_warn$', + }, + '-cn' => { + 'value' => '$journal_lag_entries_crit$', + 'set_if' => '$journal_lag_entries_crit$', + }, + }, + vars => { + 'journal_lag_warn' => 1200, + 'journal_lag_crit' => 3600, + }, + sudo => true, + sudo_user => 'journalbeat', + }, + } + + $swh_plugin_dir = '/usr/lib/nagios/plugins/swh' + $swh_plugin_configfile = '/etc/icinga2/conf.d/swh-plugins.conf' + + $packages = [ + 'python3-nagiosplugin', + 'python3-systemd', + 'monitoring-plugins-basic', + ] + package {$packages: + ensure => present, + } + + file {$swh_plugin_dir: + ensure => 'directory', + owner => 'root', + group => 'root', + mode => '0755', + recurse => true, + purge => true, + require => Package[$packages], + } + + $plugins.each |$command, $plugin| { + $command_path = "${swh_plugin_dir}/${command}" + file {$command_path: + ensure => present, + owner => 'root', + group => 'root', + mode => '0755', + source => "puppet:///modules/profile/icinga2/plugins/${command}", + require => Package[$packages], + + } + + if $plugin['sudo'] { + $sudo_user = $plugin['sudo_user'] + $icinga_command = ['sudo', '-u', $sudo_user, $command_path] + + ::sudo::conf { "icinga-${command}": + ensure => present, + content => "nagios ALL=(${sudo_user}) NOPASSWD: ${command_path}", + priority => 50, + } + } else { + $icinga_command = [$command_path] + + ::sudo::conf { "icinga-${command}": + ensure => absent, + } + } + + ::icinga2::object::checkcommand {$command: + import => ['plugin-check-command'], + command => $icinga_command, + arguments => $plugin['arguments'], + vars => $plugin['vars'], + target => $swh_plugin_configfile, + } + } +} diff --git a/site-modules/profile/manifests/icinga2/objects/apiusers.pp b/site-modules/profile/manifests/icinga2/objects/apiusers.pp new file mode 100644 index 00000000..0617ddf1 --- /dev/null +++ b/site-modules/profile/manifests/icinga2/objects/apiusers.pp @@ -0,0 +1,13 @@ +# Icinga2 API users +class profile::icinga2::objects::apiusers { + $apiuser_file = '/etc/icinga2/conf.d/api-users.conf' + $apiusers = lookup('icinga2::apiusers', Hash, 'deep') + + each($apiusers) |$name, $data| { + ::icinga2::object::apiuser {$name: + password => $data['password'], + permissions => $data['permissions'], + target => $apiuser_file, + } + } +} diff --git a/site-modules/profile/manifests/icinga2/objects/commands.pp b/site-modules/profile/manifests/icinga2/objects/commands.pp new file mode 100644 index 00000000..97f3395a --- /dev/null +++ b/site-modules/profile/manifests/icinga2/objects/commands.pp @@ -0,0 +1,49 @@ +# Icinga2 object command definitions +class profile::icinga2::objects::commands { + + $command_file = '/etc/icinga2/conf.d/commands.conf' + + $hostenv = { + 'NOTIFICATIONTYPE' => '$notification.type$', + 'HOSTALIAS' => '$host.display_name$', + 'HOSTADDRESS' => '$address$', + 'HOSTSTATE' => '$host.state$', + 'LONGDATETIME' => '$icinga.long_date_time$', + 'HOSTOUTPUT' => '$host.output$', + 'NOTIFICATIONAUTHORNAME' => '$notification.author$', + 'NOTIFICATIONCOMMENT' => '$notification.comment$', + 'HOSTDISPLAYNAME' => '$host.display_name$', + 'USEREMAIL' => '$user.email$', + } + + $serviceenv = $hostenv - 'HOSTOUTPUT' + { + 'SERVICEDESC' => '$service.name$', + 'SERVICESTATE' => '$service.state$', + 'SERVICEOUTPUT' => '$service.output$', + 'SERVICEDISPLAYNAME' => '$service.display_name$', + } + + ::icinga2::object::notificationcommand {'mail-host-notification': + command => ['/etc/icinga2/scripts/mail-host-notification.sh'], + env => $hostenv, + target => $command_file, + } + + ::icinga2::object::notificationcommand {'irc-host-notification': + command => ['/etc/icinga2/scripts/irc-host-notification.sh'], + env => $hostenv, + target => $command_file, + } + + ::icinga2::object::notificationcommand {'mail-service-notification': + command => ['/etc/icinga2/scripts/irc-service-notification.sh'], + env => $serviceenv, + target => $command_file, + } + + ::icinga2::object::notificationcommand {'irc-service-notification': + command => ['/etc/icinga2/scripts/irc-service-notification.sh'], + env => $serviceenv, + target => $command_file, + } +} diff --git a/site-modules/profile/manifests/icinga2/objects/common_checks.pp b/site-modules/profile/manifests/icinga2/objects/common_checks.pp new file mode 100644 index 00000000..27aef79b --- /dev/null +++ b/site-modules/profile/manifests/icinga2/objects/common_checks.pp @@ -0,0 +1,82 @@ +# Icinga2 common check definitions +class profile::icinga2::objects::common_checks { + $service_configuration = lookup('icinga2::service_configuration') + + # Done locally on the master + ::icinga2::object::service {'ping4': + import => ['generic-service'], + apply => true, + check_command => 'ping4', + assign => ['host.address'], + target => '/etc/icinga2/zones.d/global-templates/services.conf', + } + + ::icinga2::object::service {'linux-ssh': + import => ['generic-service'], + apply => true, + check_command => 'ssh', + assign => ['host.vars.os == Linux'], + target => '/etc/icinga2/zones.d/global-templates/services.conf', + } + + # Done remotely on the client: command_endpoint = host.name. + + each($service_configuration['load']) |$name, $vars| { + if $name == 'default' { + $assign = 'host.vars.os == Linux' + $ignore = 'host.vars.noagent || host.vars.load' + } else { + $assign = "host.vars.os == Linux && host.vars.load == ${name}" + $ignore = 'host.vars.noagent' + } + + ::icinga2::object::service {"linux_load_${name}": + import => ['generic-service'], + service_name => 'load', + apply => true, + check_command => 'load', + command_endpoint => 'host.name', + assign => [$assign], + ignore => [$ignore], + target => '/etc/icinga2/zones.d/global-templates/services.conf', + vars => $vars, + } + + } + + ::icinga2::object::service {'linux_disks': + import => ['generic-service'], + apply => 'disk_name => config in host.vars.disks', + check_command => 'disk', + command_endpoint => 'host.name', + vars => 'vars + config', + assign => ['host.vars.os == Linux'], + ignore => ['host.vars.noagent'], + target => '/etc/icinga2/zones.d/global-templates/services.conf', + } + + ::icinga2::object::service {'apt': + import => ['generic-service'], + apply => true, + check_command => 'apt', + command_endpoint => 'host.name', + check_interval => '3h', + vars => { + apt_timeout => '120', + apt_only_critical => 'true', + }, + assign => ['host.vars.os == Linux'], + ignore => ['host.vars.noagent'], + target => '/etc/icinga2/zones.d/global-templates/services.conf', + } + + ::icinga2::object::service {'journalbeat': + import => ['generic-service'], + apply => true, + check_command => 'check_journal', + command_endpoint => 'host.name', + assign => ['host.vars.os == Linux'], + ignore => ['-:"check_journal" !in host.vars.plugins', 'host.vars.noagent'], + target => '/etc/icinga2/zones.d/global-templates/services.conf', + } +} diff --git a/site-modules/profile/manifests/icinga2/objects/exported_checks.pp b/site-modules/profile/manifests/icinga2/objects/exported_checks.pp new file mode 100644 index 00000000..cef31297 --- /dev/null +++ b/site-modules/profile/manifests/icinga2/objects/exported_checks.pp @@ -0,0 +1,4 @@ +# Exported checks on the icinga agents +class profile::icinga2::objects::exported_checks { + ::Icinga2::Object::Service <<| tag == 'icinga2::exported' |>> +} diff --git a/site-modules/profile/manifests/icinga2/objects/notifications.pp b/site-modules/profile/manifests/icinga2/objects/notifications.pp new file mode 100644 index 00000000..365fad3a --- /dev/null +++ b/site-modules/profile/manifests/icinga2/objects/notifications.pp @@ -0,0 +1,19 @@ +# Icinga2 notifications +class profile::icinga2::objects::notifications { + $notification_file = '/etc/icinga2/conf.d/notifications.conf' + + $means = 'irc' + + each(['host', 'service']) |$type| { + $apply_target = "${type[0].upcase}${type[1,-1]}" + ::icinga2::object::notification {"${means}-notify-all-${type}s": + import => ["${means}-${type}-notification"], + apply => true, + apply_target => $apply_target, + assign => [true], + users => ['root'], + target => $notification_file, + interval => '12h', + } + } +} diff --git a/site-modules/profile/manifests/icinga2/objects/static_checks.pp b/site-modules/profile/manifests/icinga2/objects/static_checks.pp new file mode 100644 index 00000000..bcc529d1 --- /dev/null +++ b/site-modules/profile/manifests/icinga2/objects/static_checks.pp @@ -0,0 +1,26 @@ +# Static checks on the icinga master +class profile::icinga2::objects::static_checks { + + $checks_file = '/etc/icinga2/conf.d/static-checks.conf' + + ::icinga2::object::host {'www.softwareheritage.org': + import => ['generic-host'], + check_command => 'hostalive4', + address => 'www.softwareheritage.org', + target => $checks_file, + } + + ::icinga2::object::service {'Software Heritage Homepage': + import => ['generic-service'], + host_name => 'www.softwareheritage.org', + check_command => 'http', + target => $checks_file, + vars => { + http_vhost => 'www.softwareheritage.org', + http_uri => '/', + http_ssl => true, + http_sni => true, + http_string => 'Software Heritage', + }, + } +} diff --git a/site-modules/profile/manifests/icinga2/objects/templates.pp b/site-modules/profile/manifests/icinga2/objects/templates.pp new file mode 100644 index 00000000..8e646903 --- /dev/null +++ b/site-modules/profile/manifests/icinga2/objects/templates.pp @@ -0,0 +1,60 @@ +# Icinga2 object template definitions +class profile::icinga2::objects::templates { + + $template_file = '/etc/icinga2/conf.d/templates.conf' + + ::icinga2::object::host {'generic-host': + template => true, + max_check_attempts => 3, + check_interval => '1m', + retry_interval => '30s', + check_command => 'hostalive', + target => $template_file, + } + + ::icinga2::object::service {'generic-service': + template => true, + max_check_attempts => 5, + check_interval => '1m', + retry_interval => '30s', + target => $template_file, + } + + ::icinga2::object::user {'generic-user': + template => true, + target => $template_file, + } + + ::icinga2::object::notification {'host-notification': + template => true, + states => ['Up', 'Down'], + types => [ + 'Problem', 'Acknowledgement', 'Recovery', 'Custom', 'FlappingStart', + 'FlappingEnd', 'DowntimeStart', 'DowntimeEnd', 'DowntimeRemoved', + ], + period => '24x7', + target => $template_file, + } + + ::icinga2::object::notification {'service-notification': + template => true, + states => ['OK', 'Warning', 'Critical', 'Unknown' ], + types => [ + 'Problem', 'Acknowledgement', 'Recovery', 'Custom', 'FlappingStart', + 'FlappingEnd', 'DowntimeStart', 'DowntimeEnd', 'DowntimeRemoved', + ], + period => '24x7', + target => $template_file, + } + + each(['host', 'service']) |$type| { + each(['irc', 'mail']) |$means| { + ::icinga2::object::notification {"${means}-${type}-notification": + template => true, + import => ["${type}-notification"], + command => "${means}-${type}-notification", + target => $template_file, + } + } + } +} diff --git a/site-modules/profile/manifests/icinga2/objects/timeperiods.pp b/site-modules/profile/manifests/icinga2/objects/timeperiods.pp new file mode 100644 index 00000000..c44e9613 --- /dev/null +++ b/site-modules/profile/manifests/icinga2/objects/timeperiods.pp @@ -0,0 +1,18 @@ +# Icinga2 timeperiod definitions +class profile::icinga2::objects::timeperiods { + $timeperiod_file = '/etc/icinga2/conf.d/timeperiods.conf' + + ::icinga2::object::timeperiod {'24x7': + import => ['legacy-timeperiod'], + ranges => { + monday => '00:00-24:00', + tuesday => '00:00-24:00', + wednesday => '00:00-24:00', + thursday => '00:00-24:00', + friday => '00:00-24:00', + saturday => '00:00-24:00', + sunday => '00:00-24:00', + }, + target => $timeperiod_file, + } +} diff --git a/site-modules/profile/manifests/icinga2/objects/users.pp b/site-modules/profile/manifests/icinga2/objects/users.pp new file mode 100644 index 00000000..6bbace97 --- /dev/null +++ b/site-modules/profile/manifests/icinga2/objects/users.pp @@ -0,0 +1,10 @@ +# Icinga2 users +class profile::icinga2::objects::users { + $user_file = '/etc/icinga2/conf.d/users.conf' + + ::icinga2::object::user {'root': + import => ['generic-user'], + email => 'root', + target => $user_file, + } +} diff --git a/site-modules/profile/manifests/icinga2/plugins/rabbitmq.pp b/site-modules/profile/manifests/icinga2/plugins/rabbitmq.pp new file mode 100644 index 00000000..c1231deb --- /dev/null +++ b/site-modules/profile/manifests/icinga2/plugins/rabbitmq.pp @@ -0,0 +1,89 @@ +# RabbitMQ icinga2 plugins + +class profile::icinga2::plugins::rabbitmq { + $packages = ['nagios-plugins-rabbitmq', 'libjson-perl'] + package {$packages: + ensure => present, + } + + $plugin_configfile = '/etc/icinga2/conf.d/rabbitmq-plugins.conf' + + $base_arguments = { + '-H' => '$rabbitmq_host$', + '--port' => '$rabbitmq_port$', + '--user' => '$rabbitmq_user$', + '--password' => '$rabbitmq_password$', + '--vhost' => { + 'value' => '$rabbitmq_vhost$', + 'set_if' => '$rabbitmq_vhost$', + } + } + + $base_vars = { + 'rabbitmq_host' => '$check_address$', + 'rabbitmq_port' => '15672', + 'rabbitmq_user' => 'guest', + 'rabbitmq_password' => 'guest', + } + + $plugins = { + rabbitmq_shovels => { + arguments => $base_arguments, + vars => $base_vars, + }, + rabbitmq_partition => { + arguments => $base_arguments, + vars => $base_vars, + }, + rabbitmq_connections => { + arguments => $base_arguments, + vars => $base_vars, + }, + rabbitmq_aliveness => { + arguments => $base_arguments, + vars => $base_vars, + }, + rabbitmq_cluster => { + arguments => $base_arguments, + vars => $base_vars, + }, + rabbitmq_watermark => { + arguments => $base_arguments, + vars => $base_vars, + }, + rabbitmq_server => { + arguments => $base_arguments + { + '--node' => '$rabbitmq_node$', + }, + vars => $base_vars + { + 'rabbitmq_node' => '$check_address$', + }, + }, + rabbitmq_exchange => { + arguments => $base_arguments, + vars => $base_vars, + }, + rabbitmq_objects => { + arguments => $base_arguments, + vars => $base_vars, + }, + rabbitmq_overview => { + arguments => $base_arguments, + vars => $base_vars, + }, + rabbitmq_queue => { + arguments => $base_arguments, + vars => $base_vars, + }, + } + + $plugins.each |$command, $plugin| { + ::icinga2::object::checkcommand {$command: + import => ['plugin-check-command', 'ipv4-or-ipv6'], + command => ["-:PluginContribDir + \"-rabbitmq/check_${command}\""], + arguments => $plugin['arguments'], + vars => $plugin['vars'], + target => $plugin_configfile, + } + } +} diff --git a/site-modules/profile/manifests/jenkins/apt_config.pp b/site-modules/profile/manifests/jenkins/apt_config.pp new file mode 100644 index 00000000..266b718a --- /dev/null +++ b/site-modules/profile/manifests/jenkins/apt_config.pp @@ -0,0 +1,19 @@ +class profile::jenkins::apt_config { + $mirror = lookup('jenkins::apt_config::mirror') + $keyid = lookup('jenkins::apt_config::keyid') + $key = lookup('jenkins::apt_config::key') + + apt::source {'jenkins': + location => $mirror, + release => 'binary/', + repos => '', + key => { + id => $keyid, + content => $key, + }, + include => { + src => false, + deb => true, + } + } +} diff --git a/site-modules/profile/manifests/jenkins/server.pp b/site-modules/profile/manifests/jenkins/server.pp new file mode 100644 index 00000000..0b62bf53 --- /dev/null +++ b/site-modules/profile/manifests/jenkins/server.pp @@ -0,0 +1,3 @@ +class profile::jenkins::server { + include profile::jenkins::service +} diff --git a/site-modules/profile/manifests/jenkins/service.pp b/site-modules/profile/manifests/jenkins/service.pp new file mode 100644 index 00000000..c9b6a3b5 --- /dev/null +++ b/site-modules/profile/manifests/jenkins/service.pp @@ -0,0 +1,12 @@ +class profile::jenkins::service { + include profile::jenkins::apt_config + + package {'jenkins': + ensure => present, + require => Apt::Source['jenkins'], + } + -> service {'jenkins': + ensure => running, + enable => true, + } +} diff --git a/site-modules/profile/manifests/jenkins/worker.pp b/site-modules/profile/manifests/jenkins/worker.pp new file mode 100644 index 00000000..141c56ae --- /dev/null +++ b/site-modules/profile/manifests/jenkins/worker.pp @@ -0,0 +1,16 @@ +class profile::jenkins::worker { + include profile::docker + include profile::jenkins::service + + exec {'add jenkins user to docker group': + path => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'], + command => 'gpasswd -a jenkins docker', + onlyif => 'getent passwd jenkins', + unless => 'getent group docker | cut -d: -f4 | grep -qE \'(^|,)jenkins(,|$)\'', + require => [ + Package['docker-ce'], + Package['jenkins'], + ], + notify => Service['jenkins'], + } +} diff --git a/site-modules/profile/manifests/kafka/broker.pp b/site-modules/profile/manifests/kafka/broker.pp new file mode 100644 index 00000000..290bb9e8 --- /dev/null +++ b/site-modules/profile/manifests/kafka/broker.pp @@ -0,0 +1,29 @@ +# Kafka broker profile + +class profile::kafka::broker { + include ::profile::zookeeper + + class {'::kafka': + mirror_url => lookup('kafka::mirror_url'), + version => lookup('kafka::version'), + scala_version => lookup('kafka::scala_version'), + } + + $base_kafka_config = lookup('kafka::broker_config', Hash) + + $zookeeper_chroot = lookup('kafka::zookeeper::chroot') + $zookeeper_servers = lookup('zookeeper::servers', Hash) + $zookeeper_port = lookup('zookeeper::client_port', Integer) + $zookeeper_connect_string = join( + $zookeeper_servers.map |$id, $server| {"${server}:${zookeeper_port}${zookeeper_chroot}"}, + ',' + ) + + $kafka_config = $base_kafka_config + { + 'zookeeper.connect' => $zookeeper_connect_string, + } + + class {'::kafka::broker': + config => $kafka_config, + } +} diff --git a/site-modules/profile/manifests/mediawiki.pp b/site-modules/profile/manifests/mediawiki.pp new file mode 100644 index 00000000..dff061ca --- /dev/null +++ b/site-modules/profile/manifests/mediawiki.pp @@ -0,0 +1,136 @@ +# Deployment of mediawiki for the Software Heritage intranet +class profile::mediawiki { + $mediawiki_fpm_root = lookup('mediawiki::php::fpm_listen') + + $mediawiki_vhosts = lookup('mediawiki::vhosts', Hash, 'deep') + + include ::profile::php + + ::php::fpm::pool {'mediawiki': + listen => $mediawiki_fpm_root, + user => 'www-data', + } + + include ::profile::ssl + + $ssl_cert_name = 'star_softwareheritage_org' + $ssl_cert = $::profile::ssl::certificate_paths[$ssl_cert_name] + $ssl_chain = $::profile::ssl::chain_paths[$ssl_cert_name] + $ssl_key = $::profile::ssl::private_key_paths[$ssl_cert_name] + + include ::mediawiki + + $mediawiki_vhost_docroot = lookup('mediawiki::vhost::docroot') + $mediawiki_vhost_ssl_protocol = lookup('mediawiki::vhost::ssl_protocol') + $mediawiki_vhost_ssl_honorcipherorder = lookup('mediawiki::vhost::ssl_honorcipherorder') + $mediawiki_vhost_ssl_cipher = lookup('mediawiki::vhost::ssl_cipher') + $mediawiki_vhost_hsts_header = lookup('mediawiki::vhost::hsts_header') + + $icinga_checks_file = '/etc/icinga2/conf.d/exported-checks.conf' + + each ($mediawiki_vhosts) |$name, $data| { + $secret_key = $data['secret_key'] + $upgrade_key = $data['upgrade_key'] + $site_name = $data['site_name'] + $basic_auth_content = $data['basic_auth_content'] + + ::mediawiki::instance { $name: + vhost_docroot => $mediawiki_vhost_docroot, + vhost_aliases => $data['aliases'], + vhost_fpm_root => $mediawiki_fpm_root, + vhost_basic_auth => $basic_auth_content, + vhost_ssl_protocol => $mediawiki_vhost_ssl_protocol, + vhost_ssl_honorcipherorder => $mediawiki_vhost_ssl_honorcipherorder, + vhost_ssl_cipher => $mediawiki_vhost_ssl_cipher, + vhost_ssl_cert => $ssl_cert, + vhost_ssl_chain => $ssl_chain, + vhost_ssl_key => $ssl_key, + vhost_ssl_hsts_header => $mediawiki_vhost_hsts_header, + db_host => 'localhost', + db_basename => $data['mysql']['dbname'], + db_user => $data['mysql']['username'], + db_password => $data['mysql']['password'], + secret_key => $secret_key, + upgrade_key => $upgrade_key, + swh_logo => $data['swh_logo'], + site_name => $site_name, + } + + @@::icinga2::object::service {"mediawiki (${name}) http redirect on ${::fqdn}": + service_name => "mediawiki ${name} http redirect", + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $name, + http_vhost => $name, + http_uri => '/', + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + if $basic_auth_content != '' { + $extra_vars = { + http_expect => '401 Unauthorized', + } + + @@::icinga2::object::service {"mediawiki ${name} https + auth on ${::fqdn}": + service_name => "mediawiki ${name} + auth", + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $name, + http_vhost => $name, + http_ssl => true, + http_sni => true, + http_uri => '/', + http_onredirect => sticky, + http_auth_pair => $data['icinga_http_auth_pair'], + http_string => "${site_name}", + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + } else { + $extra_vars = { + http_string => "${site_name}", + } + } + + @@::icinga2::object::service {"mediawiki ${name} https on ${::fqdn}": + service_name => "mediawiki ${name}", + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $name, + http_vhost => $name, + http_ssl => true, + http_sni => true, + http_uri => '/', + http_onredirect => sticky, + } + $extra_vars, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + @@::icinga2::object::service {"mediawiki ${name} https certificate ${::fqdn}": + service_name => "mediawiki ${name} https certificate", + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_vhost => $name, + http_address => $name, + http_ssl => true, + http_sni => true, + http_certificate => 60, + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + } +} diff --git a/site-modules/profile/manifests/memcached.pp b/site-modules/profile/manifests/memcached.pp new file mode 100644 index 00000000..0c35c3cc --- /dev/null +++ b/site-modules/profile/manifests/memcached.pp @@ -0,0 +1,12 @@ +# Install and configure local memcached server +class profile::memcached { + $memcached_bind = lookup('memcached::server::bind') + $memcached_port = lookup('memcached::server::port') + $memcached_memory = lookup('memcached::server::max_memory') + + class {'::memcached': + listen_ip => $memcached_bind, + tcp_port => $memcached_port, + max_memory => $memcached_max_memory, + } +} diff --git a/site-modules/profile/manifests/mountpoints.pp b/site-modules/profile/manifests/mountpoints.pp new file mode 100644 index 00000000..8ab2beb9 --- /dev/null +++ b/site-modules/profile/manifests/mountpoints.pp @@ -0,0 +1,31 @@ +# Handle mount points +class profile::mountpoints { + $mountpoints = lookup('mountpoints', Hash, 'deep') + + each($mountpoints) |$mountpoint, $config| { + if (has_key($config, 'options') and $config['options'] =~ Array) { + $mount_config = $config + { + options => join($config['options'], ','), + } + } else { + $mount_config = $config + } + + exec {"create ${mountpoint}": + creates => $mountpoint, + command => "mkdir -p ${mountpoint}", + path => ['/bin', '/usr/bin', '/sbin', '/usr/sbin'], + } -> file {$mountpoint:} + + mount { + default: + ensure => present, + dump => 0, + pass => 0, + options => 'defaults'; + $mountpoint: + * => $mount_config, + require => File[$mountpoint], + } + } +} diff --git a/site-modules/profile/manifests/munin/master.pp b/site-modules/profile/manifests/munin/master.pp new file mode 100644 index 00000000..f7a518b8 --- /dev/null +++ b/site-modules/profile/manifests/munin/master.pp @@ -0,0 +1,59 @@ +# Munin master class +class profile::munin::master { + $master_hostname = lookup('munin::master::hostname') + $master_hostname_domain = join(delete_at(split($master_hostname, '[.]'), 0), '.') + $master_hostname_target = "${::hostname}.${master_hostname_domain}." + + class { '::munin::master': + extra_config => ["cgiurl_graph http://$master_hostname"], + } + + include ::profile::apache::common + include ::apache::mod::rewrite + include ::apache::mod::fcgid + + apache::vhost { $master_hostname: + port => 80, + docroot => '/var/www/html', + rewrites => [ + { + comment => 'static resources', + rewrite_rule => [ + '^/favicon.ico /etc/munin/static/favicon.ico [L]', + '^/static/(.*) /etc/munin/static/$1 [L]', + ], + }, + { + comment => 'HTML', + rewrite_cond => [ + '%{REQUEST_URI} .html$ [or]', + '%{REQUEST_URI} =/', + ], + rewrite_rule => [ + '^/(.*) /usr/lib/munin/cgi/munin-cgi-html/$1 [L]', + ], + }, + { + comment => 'Images', + rewrite_rule => [ + '^/munin-cgi/munin-cgi-graph/(.*) /usr/lib/munin/cgi/munin-cgi-graph/$1 [L]', + '^/(.*) /usr/lib/munin/cgi/munin-cgi-graph/$1 [L]', + ], + }, + ], + directories => [ + { 'path' => '/usr/lib/munin/cgi', + 'options' => '+ExecCGI', + 'sethandler' => 'fcgid-script' }, + ], + } + + $bind_key = lookup('bind::update_key') + + @@resource_record { 'munin/CNAME': + record => $master_hostname, + type => 'CNAME', + data => $master_hostname_target, + keyfile => "/etc/bind/keys/${bind_key}", + } +} diff --git a/site-modules/profile/manifests/munin/node.pp b/site-modules/profile/manifests/munin/node.pp new file mode 100644 index 00000000..6db0cfb8 --- /dev/null +++ b/site-modules/profile/manifests/munin/node.pp @@ -0,0 +1,41 @@ +# Munin node class +class profile::munin::node { + $munin_node_allow = lookup('munin::node::allow') + $munin_node_network = lookup('munin::node::network') + $munin_node_plugins_disable = lookup('munin::node::plugins::disable', Array, 'unique') + $munin_node_plugins_enable = lookup('munin::node::plugins::enable', Array, 'unique') + + class { '::munin::node': + allow => $munin_node_allow, + address => ip_for_network($munin_node_network), + bind_address => ip_for_network($munin_node_network), + masterconfig => [ + '', + '# The apt plugin doesn\'t graph by default. Let\'s make it.', + 'apt.graph yes', + 'apt.graph_category system', + 'apt.graph_vlabel Total Packages', + '', + '# Move the libvirt plugins to a spaceless category', + 'libvirt_blkstat.graph_category virtualization', + 'libvirt_cputime.graph_category virtualization', + 'libvirt_ifstat.graph_category virtualization', + 'libvirt_mem.graph_category virtualization', + ], + } + + munin::plugin { $munin_node_plugins_enable: + ensure => link, + } + munin::plugin { $munin_node_plugins_disable: + ensure => absent, + } + + file_line { 'disable munin-node cron mail': + ensure => present, + path => '/etc/cron.d/munin-node', + line => 'MAILTO=""', + match => '^MAILTO=', + require => Package['munin-node'], + } +} diff --git a/site-modules/profile/manifests/munin/plugins/apache.pp b/site-modules/profile/manifests/munin/plugins/apache.pp new file mode 100644 index 00000000..a28bb1f4 --- /dev/null +++ b/site-modules/profile/manifests/munin/plugins/apache.pp @@ -0,0 +1,13 @@ +# Munin plugins for Apache + +class profile::munin::plugins::apache { + munin::plugin { 'apache_volume': + ensure => link, + } + munin::plugin { 'apache_accesses': + ensure => link, + } + munin::plugin { 'apache_processes': + ensure => link, + } +} diff --git a/site-modules/profile/manifests/munin/plugins/postgresql.pp b/site-modules/profile/manifests/munin/plugins/postgresql.pp new file mode 100644 index 00000000..ddb85b95 --- /dev/null +++ b/site-modules/profile/manifests/munin/plugins/postgresql.pp @@ -0,0 +1,60 @@ +class profile::munin::plugins::postgresql { + munin::plugin { 'postgres_autovacuum': + ensure => link, + } + munin::plugin { 'postgres_bgwriter': + ensure => link, + } + munin::plugin { 'postgres_cache_ALL': + ensure => link, + target => 'postgres_cache_', + } + munin::plugin { 'postgres_checkpoints': + ensure => link, + } + munin::plugin { 'postgres_connections_ALL': + ensure => link, + target => 'postgres_connections_', + } + munin::plugin { 'postgres_connections_db': + ensure => link, + } + munin::plugin { 'postgres_locks_ALL': + ensure => link, + target => 'postgres_locks_' + } + munin::plugin { 'postgres_querylength_ALL': + ensure => link, + target => 'postgres_querylength_', + } + munin::plugin { 'postgres_scans_ALL': + ensure => link, + target => 'postgres_scans_', + } + munin::plugin { 'postgres_size_ALL': + ensure => link, + target => 'postgres_size_', + } + munin::plugin { 'postgres_streaming_ALL': + ensure => link, + target => 'postgres_streaming_', + } + munin::plugin { 'postgres_transactions_ALL': + ensure => link, + target => 'postgres_transactions_', + } + munin::plugin { 'postgres_tuples_ALL': + ensure => link, + target => 'postgres_tuples_', + } + munin::plugin { 'postgres_users': + ensure => link, + } + munin::plugin { 'postgres_xlog': + ensure => link, + } + + package { 'libdbd-pg-perl': + ensure => 'present', + } -> Munin::Plugin <| |> +} diff --git a/site-modules/profile/manifests/munin/plugins/rabbitmq.pp b/site-modules/profile/manifests/munin/plugins/rabbitmq.pp new file mode 100644 index 00000000..e8c0ca08 --- /dev/null +++ b/site-modules/profile/manifests/munin/plugins/rabbitmq.pp @@ -0,0 +1,41 @@ +class profile::munin::plugins::rabbitmq { + $messages_warn = lookup('munin::plugins::rabbitmq::messages_warn') + $messages_crit = lookup('munin::plugins::rabbitmq::messages_crit') + $queue_memory_warn = lookup('munin::plugins::rabbitmq::queue_memory_warn') + $queue_memory_crit = lookup('munin::plugins::rabbitmq::queue_memory_crit') + + munin::plugin { + 'rabbitmq_connections': + ensure => present, + source => 'puppet:///modules/profile/munin/rabbitmq/rabbitmq_connections', + config => ['user root']; + 'rabbitmq_consumers': + ensure => present, + source => 'puppet:///modules/profile/munin/rabbitmq/rabbitmq_consumers', + config => ['user root']; + 'rabbitmq_messages': + ensure => present, + source => 'puppet:///modules/profile/munin/rabbitmq/rabbitmq_messages', + config => [ + 'user root', + "env.queue_warn ${messages_warn}", + "env.queue_crit ${messages_crit}", + ]; + 'rabbitmq_messages_unacknowledged': + ensure => present, + source => 'puppet:///modules/profile/munin/rabbitmq/rabbitmq_messages_unacknowledged', + config => ['user root']; + 'rabbitmq_messages_uncommitted': + ensure => present, + source => 'puppet:///modules/profile/munin/rabbitmq/rabbitmq_messages_uncommitted', + config => ['user root']; + 'rabbitmq_queue_memory': + ensure => present, + source => 'puppet:///modules/profile/munin/rabbitmq/rabbitmq_queue_memory', + config => [ + 'user root', + "env.queue_warn ${queue_memory_warn}", + "env.queue_crit ${queue_memory_crit}", + ]; + } +} diff --git a/site-modules/profile/manifests/munin/stats_export.pp b/site-modules/profile/manifests/munin/stats_export.pp new file mode 100644 index 00000000..79a9d353 --- /dev/null +++ b/site-modules/profile/manifests/munin/stats_export.pp @@ -0,0 +1,84 @@ +# stats_export master class +class profile::munin::stats_export { + $vhost_name = lookup('stats_export::vhost::name') + $vhost_docroot = lookup('stats_export::vhost::docroot') + $vhost_ssl_protocol = lookup('stats_export::vhost::ssl_protocol') + $vhost_ssl_honorcipherorder = lookup('stats_export::vhost::ssl_honorcipherorder') + $vhost_ssl_cipher = lookup('stats_export::vhost::ssl_cipher') + $vhost_hsts_header = lookup('stats_export::vhost::hsts_header') + + $export_file = "${vhost_docroot}/history_counters.json" + + $packages = ['python3-click'] + + package {$packages: + ensure => present, + } + + file {'/usr/local/bin/export-rrd': + ensure => present, + owner => 'root', + group => 'root', + mode => '0755', + source => 'puppet:///modules/profile/munin/stats_export/export-rrd', + require => Package[$packages], + } + + cron {'stats_export': + ensure => present, + user => 'www-data', + command => "/usr/local/bin/export-rrd > ${export_file}.tmp && /bin/mv ${export_file}.tmp ${export_file}", + hour => fqdn_rand(24, 'stats_export_hour'), + minute => fqdn_rand(60, 'stats_export_minute'), + month => '*', + monthday => '*', + weekday => '*', + require => [ + File['/usr/local/bin/export-rrd'], + File[$vhost_docroot], + ], + } + + file {$vhost_docroot: + ensure => directory, + owner => 'www-data', + group => 'www-data', + mode => '0755', + } + + include ::profile::apache::common + include ::profile::ssl + + ::apache::vhost {"${vhost_name}_non-ssl": + servername => $vhost_name, + port => '80', + docroot => $vhost_docroot, + redirect_status => 'permanent', + redirect_dest => "https://${vhost_name}/", + } + + $ssl_cert_name = 'stats_export_softwareheritage_org' + $ssl_cert = $::profile::ssl::certificate_paths[$ssl_cert_name] + $ssl_chain = $::profile::ssl::chain_paths[$ssl_cert_name] + $ssl_key = $::profile::ssl::private_key_paths[$ssl_cert_name] + + ::apache::vhost {"${vhost_name}_ssl": + servername => $vhost_name, + port => '443', + ssl => true, + ssl_protocol => $vhost_ssl_protocol, + ssl_honorcipherorder => $vhost_ssl_honorcipherorder, + ssl_cipher => $vhost_ssl_cipher, + ssl_cert => $ssl_cert, + ssl_chain => $ssl_chain, + ssl_key => $ssl_key, + headers => [$vhost_hsts_header], + docroot => $vhost_docroot, + require => [ + File[$ssl_cert], + File[$ssl_chain], + File[$ssl_key], + ], + } + +} diff --git a/site-modules/profile/manifests/network.pp b/site-modules/profile/manifests/network.pp new file mode 100644 index 00000000..70ec6b32 --- /dev/null +++ b/site-modules/profile/manifests/network.pp @@ -0,0 +1,47 @@ +# Network configuration for Software Heritage servers +# +# Supports one private and one public interface +class profile::network { + debnet::iface::loopback { 'lo': } + + $interfaces = lookup('networks') + each($interfaces) |$label, $data| { + + if $label == 'private' { + file_line {'private route table': + ensure => 'present', + line => '42 private', + path => '/etc/iproute2/rt_tables', + } + $ups = [ + "ip route add 192.168.101.0/24 via ${data['gateway']}", + "ip route add 192.168.200.0/21 via ${data['gateway']}", + "ip rule add from ${data['address']} table private", + "ip route add default via ${data['gateway']} dev ${data['interface']} table private", + 'ip route flush cache', + ] + $downs = [ + "ip route del default via ${data['gateway']} dev ${data['interface']} table private", + "ip rule del from ${data['address']} table private", + "ip route del 192.168.200.0/24 via ${data['gateway']}", + "ip route del 192.168.101.0/24 via ${data['gateway']}", + 'ip route flush cache', + ] + $gateway = undef + } else { + $ups = [] + $downs = [] + $gateway = $data['gateway'] + } + + + debnet::iface { $data['interface']: + method => 'static', + address => $data['address'], + netmask => $data['netmask'], + gateway => $gateway, + ups => $ups, + downs => $downs, + } + } +} diff --git a/site-modules/profile/manifests/nginx.pp b/site-modules/profile/manifests/nginx.pp new file mode 100644 index 00000000..00e7c77e --- /dev/null +++ b/site-modules/profile/manifests/nginx.pp @@ -0,0 +1,34 @@ +# Deployment of nginx as a reverse proxy for Software Heritage RPC servers + +class profile::nginx { + $accept_mutex = lookup('nginx::accept_mutex') + $package_name = lookup('nginx::package_name') + + $names_hash_bucket_size = lookup('nginx::names_hash_bucket_size') + $names_hash_max_size = lookup('nginx::names_hash_max_size') + $worker_processes = lookup('nginx::worker_processes') + if $worker_processes != 'auto' { + $actual_worker_processes = $worker_processes + 0 + } else { + $actual_worker_processes = 'auto' + } + + class {'::nginx': + package_name => $package_name, + manage_repo => false, + accept_mutex => $accept_mutex, + names_hash_bucket_size => $names_hash_bucket_size, + names_hash_max_size => $names_hash_max_size, + worker_processes => $actual_worker_processes, + } + + ::nginx::resource::map {'error_status': + ensure => present, + string => "\$status", + default => '1', + mappings => { + '~^[23]' => '0', + '404' => '0', + } + } +} diff --git a/site-modules/profile/manifests/phabricator.pp b/site-modules/profile/manifests/phabricator.pp new file mode 100644 index 00000000..dbb7c7b5 --- /dev/null +++ b/site-modules/profile/manifests/phabricator.pp @@ -0,0 +1,305 @@ +# Setup an instance of phabricator +class profile::phabricator { + $phabricator_basepath = lookup('phabricator::basepath') + $phabricator_user = lookup('phabricator::user') + $phabricator_vcs_user = lookup('phabricator::vcs_user') + + $phabricator_db_root_password = lookup('phabricator::mysql::root_password') + $phabricator_db_basename = lookup('phabricator::mysql::database_prefix') + $phabricator_db_user = lookup('phabricator::mysql::username') + $phabricator_db_password = lookup('phabricator::mysql::password') + + $phabricator_db_max_allowed_packet = lookup('phabricator::mysql::conf::max_allowed_packet') + $phabricator_db_sql_mode = lookup('phabricator::mysql::conf::sql_mode') + $phabricator_db_ft_stopword_file = lookup('phabricator::mysql::conf::ft_stopword_file') + $phabricator_db_ft_min_word_len = lookup('phabricator::mysql::conf::ft_min_word_len') + $phabricator_db_ft_boolean_syntax = lookup('phabricator::mysql::conf::ft_boolean_syntax') + $phabricator_db_innodb_buffer_pool_size = lookup('phabricator::mysql::conf::innodb_buffer_pool_size') + $phabricator_db_innodb_file_per_table = lookup('phabricator::mysql::conf::innodb_file_per_table') + $phabricator_db_innodb_flush_method = lookup('phabricator::mysql::conf::innodb_flush_method') + $phabricator_db_innodb_log_file_size = lookup('phabricator::mysql::conf::innodb_log_file_size') + + $phabricator_fpm_listen = lookup('phabricator::php::fpm_listen') + $phabricator_max_size = lookup('phabricator::php::max_file_size') + $phabricator_opcache_validate_timestamps = lookup('phabricator::php::opcache_validate_timestamps') + + $phabricator_notification_listen = lookup('phabricator::notification::listen') + $phabricator_notification_client_host = lookup('phabricator::notification::client_host') + $phabricator_notification_client_port = lookup('phabricator::notification::client_port') + + $phabricator_vhost_name = lookup('phabricator::vhost::name') + $phabricator_vhost_docroot = lookup('phabricator::vhost::docroot') + $phabricator_vhost_basic_auth_file = "${phabricator_basepath}/http_auth" + $phabricator_vhost_basic_auth_content = lookup('phabricator::vhost::basic_auth_content') + $phabricator_vhost_ssl_protocol = lookup('phabricator::vhost::ssl_protocol') + $phabricator_vhost_ssl_honorcipherorder = lookup('phabricator::vhost::ssl_honorcipherorder') + $phabricator_vhost_ssl_cipher = lookup('phabricator::vhost::ssl_cipher') + $phabricator_vhost_hsts_header = lookup('phabricator::vhost::hsts_header') + + $homedirs = { + $phabricator_user => $phabricator_basepath, + $phabricator_vcs_user => "${phabricator_basepath}/vcshome", + } + + $homedir_modes = { + $phabricator_user => '0644', + $phabricator_vcs_user => '0640', + } + + each([$phabricator_user, $phabricator_vcs_user]) |$name| { + user {$name: + ensure => present, + system => true, + shell => '/bin/bash', + home => $homedirs[$name], + } + + file {$homedirs[$name]: + ensure => directory, + owner => $name, + group => $name, + mode => $homedir_modes[$name], + } + } + + ::sudo::conf {'phabricator-ssh': + ensure => present, + content => "${phabricator_vcs_user} ALL=(${phabricator_user}) SETENV: NOPASSWD: /usr/bin/git-upload-pack, /usr/bin/git-receive-pack, /usr/bin/hg", + } + + ::sudo::conf {'phabricator-http': + ensure => present, + content => "www-data ALL=(${phabricator_user}) SETENV: NOPASSWD: /usr/bin/git-http-backend, /usr/bin/hg", + require => File['/usr/bin/git-http-backend'], + } + + file {'/usr/bin/git-http-backend': + ensure => link, + target => '/usr/lib/git-core/git-http-backend', + } + + $phabricator_ssh_hook = '/usr/bin/phabricator-ssh-hook.sh' + $phabricator_ssh_config = '/etc/ssh/ssh_config.phabricator' + + file {$phabricator_ssh_hook: + ensure => present, + owner => 'root', + group => 'root', + mode => '0755', + content => template('profile/phabricator/phabricator-ssh-hook.sh.erb'), + } + + file {$phabricator_ssh_config: + ensure => present, + owner => 'root', + group => 'root', + mode => '0600', + content => template('profile/phabricator/sshd_config.phabricator.erb'), + require => File[$phabricator_ssh_hook], + } + + ::systemd::unit_file {'phabricator-sshd.service': + ensure => present, + content => template('profile/phabricator/phabricator-sshd.service.erb'), + require => File[$phabricator_ssh_config], + } ~> service {'phabricator-sshd': + ensure => 'running', + enable => true, + require => [ + File['/etc/systemd/system/phabricator-sshd.service'], + ], + } + + include ::mysql::client + + class {'::mysql::server': + root_password => $phabricator_db_root_password, + override_options => { + mysqld => { + max_allowed_packet => $phabricator_db_max_allowed_packet, + sql_mode => $phabricator_db_sql_mode, + ft_stopword_file => $phabricator_db_ft_stopword_file, + ft_min_word_len => $phabricator_db_ft_min_word_len, + ft_boolean_syntax => $phabricator_db_ft_boolean_syntax, + innodb_buffer_pool_size => $phabricator_db_innodb_buffer_pool_size, + innodb_file_per_table => $phabricator_db_innodb_file_per_table, + innodb_flush_method => $phabricator_db_innodb_flush_method, + innodb_log_file_size => $phabricator_db_innodb_log_file_size, + } + } + } + + $mysql_username = "${phabricator_db_user}@localhost" + $mysql_tables = "${phabricator_db_basename}_%.*" + + mysql_user {$mysql_username: + ensure => present, + password_hash => mysql_password($phabricator_db_password), + } + + mysql_grant {"${mysql_username}/${mysql_tables}": + user => $mysql_username, + table => $mysql_tables, + privileges => ['ALL'], + require => Mysql_user[$mysql_username], + } + + include ::profile::php + + ::php::fpm::pool {'phabricator': + listen => $phabricator_fpm_listen, + user => 'www-data', + php_admin_value => { + post_max_size => $phabricator_max_size, + upload_max_filesize => $phabricator_max_size, + 'opcache.validate_timestamps' => $phabricator_opcache_validate_timestamps, + }, + } + + ::php::extension {[ + 'apcu', + 'mailparse', + ]: + provider => 'apt', + package_prefix => 'php-', + } + + ::php::extension {[ + 'curl', + 'gd', + ]: + provider => 'apt', + } + + include ::profile::ssl + include ::profile::apache::common + include ::apache::mod::proxy + include ::profile::apache::mod_proxy_fcgi + + ::apache::mod {'proxy_wstunnel':} + + ::apache::vhost {"${phabricator_vhost_name}_non-ssl": + servername => $phabricator_vhost_name, + port => '80', + docroot => $phabricator_vhost_docroot, + docroot_owner => $phabricator_user, + docroot_group => $phabricator_user, + redirect_status => 'permanent', + redirect_dest => "https://${phabricator_vhost_name}/", + } + + $ssl_cert_name = 'star_softwareheritage_org' + $ssl_cert = $::profile::ssl::certificate_paths[$ssl_cert_name] + $ssl_chain = $::profile::ssl::chain_paths[$ssl_cert_name] + $ssl_key = $::profile::ssl::private_key_paths[$ssl_cert_name] + + ::apache::vhost {"${phabricator_vhost_name}_ssl": + servername => $phabricator_vhost_name, + port => '443', + ssl => true, + ssl_protocol => $phabricator_vhost_ssl_protocol, + ssl_honorcipherorder => $phabricator_vhost_ssl_honorcipherorder, + ssl_cipher => $phabricator_vhost_ssl_cipher, + ssl_cert => $ssl_cert, + ssl_chain => $ssl_chain, + ssl_key => $ssl_key, + headers => [$phabricator_vhost_hsts_header], + docroot => $phabricator_vhost_docroot, + docroot_owner => $phabricator_user, + docroot_group => $phabricator_user, + rewrites => [ + { rewrite_rule => '^/rsrc/(.*) - [L,QSA]' }, + { rewrite_rule => '^/favicon.ico - [L,QSA]' }, + { rewrite_rule => "^/ws/(.*)$ ws://${phabricator_notification_listen}/\$1 [L,P]" }, + { rewrite_rule => "^(.*)$ fcgi://${phabricator_fpm_listen}${phabricator_vhost_docroot}/index.php?__path__=\$1 [B,L,P,QSA]" }, + ], + setenvif => [ + "Authorization \"(.*)\" HTTP_AUTHORIZATION=\$1", + ], + require => [ + File[$ssl_cert], + File[$ssl_chain], + File[$ssl_key], + ], + } + + file {$phabricator_vhost_basic_auth_file: + ensure => absent, + } + + # Uses: + # $phabricator_basepath + # $phabricator_user + ::systemd::unit_file {'phabricator-phd.service': + ensure => present, + content => template('profile/phabricator/phabricator-phd.service.erb'), + } ~> service {'phabricator-phd': + ensure => 'running', + enable => true, + } + + # Uses: + # $phabricator_basepath + # $phabricator_user + # $phabricator_notification_* + ::systemd::unit_file {'phabricator-aphlict.service': + ensure => present, + content => template('profile/phabricator/phabricator-aphlict.service.erb'), + } ~> service {'phabricator-aphlict': + ensure => 'running', + enable => true, + } + + package {'python-pygments': + ensure => installed, + } + + $icinga_checks_file = '/etc/icinga2/conf.d/exported-checks.conf' + + @@::icinga2::object::service {"phabricator http redirect on ${::fqdn}": + service_name => 'phabricator http redirect', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $phabricator_vhost_name, + http_vhost => $phabricator_vhost_name, + http_uri => '/', + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + @@::icinga2::object::service {"phabricator https on ${::fqdn}": + service_name => 'phabricator', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $phabricator_vhost_name, + http_vhost => $phabricator_vhost_name, + http_ssl => true, + http_sni => true, + http_uri => '/', + http_onredirect => sticky + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + @@::icinga2::object::service {"phabricator https certificate ${::fqdn}": + service_name => 'phabricator https certificate', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $phabricator_vhost_name, + http_vhost => $phabricator_vhost_name, + http_ssl => true, + http_sni => true, + http_certificate => 60, + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } +} diff --git a/site-modules/profile/manifests/php.pp b/site-modules/profile/manifests/php.pp new file mode 100644 index 00000000..edfffeed --- /dev/null +++ b/site-modules/profile/manifests/php.pp @@ -0,0 +1,40 @@ +# Manage base PHP installation +class profile::php { + $php_mirror = lookup('php::apt_config::mirror') + $php_keyid = lookup('php::apt_config::keyid') + $php_key = lookup('php::apt_config::key') + + ::apt::source {'php': + location => $php_mirror, + release => $facts['os']['distro']['codename'], + repos => 'main', + key => { + id => $php_keyid, + content => $php_key, + }, + } + + $php_version = lookup('php::version') + + class {'::php::globals': + php_version => $php_version, + } + -> class {'::php': + manage_repos => false, + dev => false, + composer => false, + pear => false, + fpm => false, + } + class {'::php::fpm': + pools => {}, + } + + package {"php${php_version}-mysql": + ensure => installed, + } + -> ::php::extension {['mysqlnd', 'mysqli', 'pdo_mysql']: + provider => 'none', + } + +} diff --git a/site-modules/profile/manifests/postgresql.pp b/site-modules/profile/manifests/postgresql.pp new file mode 100644 index 00000000..b216cb7a --- /dev/null +++ b/site-modules/profile/manifests/postgresql.pp @@ -0,0 +1,4 @@ +# Manage a PostgreSQL server +class profile::postgresql { + include profile::postgresql::apt_config +} diff --git a/site-modules/profile/manifests/postgresql/apt_config.pp b/site-modules/profile/manifests/postgresql/apt_config.pp new file mode 100644 index 00000000..55f8b122 --- /dev/null +++ b/site-modules/profile/manifests/postgresql/apt_config.pp @@ -0,0 +1,29 @@ +# PostgreSQL APT configuration +class profile::postgresql::apt_config { + $pgdg_mirror = lookup('postgresql::apt_config::pgdg::mirror') + $pgdg_keyid = lookup('postgresql::apt_config::pgdg::keyid') + $pgdg_key = lookup('postgresql::apt_config::pgdg::key') + $pglogical_mirror = lookup('postgresql::apt_config::pglogical::mirror') + $pglogical_keyid = lookup('postgresql::apt_config::pglogical::keyid') + $pglogical_key = lookup('postgresql::apt_config::pglogical::key') + + ::apt::source {'pgdg': + location => $pgdg_mirror, + release => "${::lsbdistcodename}-pgdg", + repos => 'main', + key => { + id => $pgdg_keyid, + content => $pgdg_key, + }, + } + + ::apt::source {'pglogical': + location => $pglogical_mirror, + release => "${::lsbdistcodename}-2ndquadrant", + repos => 'main', + key => { + id => $pglogical_keyid, + content => $pglogical_key, + }, + } +} diff --git a/site-modules/profile/manifests/prometheus/apt_config.pp b/site-modules/profile/manifests/prometheus/apt_config.pp new file mode 100644 index 00000000..c8fe254d --- /dev/null +++ b/site-modules/profile/manifests/prometheus/apt_config.pp @@ -0,0 +1,22 @@ +# APT configuration for prometheus +class profile::prometheus::apt_config { + if $facts['os']['distro']['codename'] == 'stretch' { + $pinned_packages = [ + 'prometheus', + 'prometheus-alertmanager', + 'prometheus-node-exporter', + ] + + ::apt::pin {'prometheus': + explanation => 'Pin prometheus to backports', + codename => 'stretch-backports', + packages => $pinned_packages, + priority => 990, + } + + } else { + ::apt::pin {'prometheus': + ensure => absent + } + } +} diff --git a/site-modules/profile/manifests/prometheus/export_scrape_config.pp b/site-modules/profile/manifests/prometheus/export_scrape_config.pp new file mode 100644 index 00000000..471e4cf3 --- /dev/null +++ b/site-modules/profile/manifests/prometheus/export_scrape_config.pp @@ -0,0 +1,14 @@ +# Export a scrape config to the configured prometheus server +define profile::prometheus::export_scrape_config ( + String $target, + String $job = $name, + Optional[String] $prometheus_server = undef, + Hash[String, String] $labels = {}, +) { + @@profile::prometheus::scrape_config {"${facts['swh_hostname']['short']}_${name}": + prometheus_server => pick($prometheus_server, lookup('prometheus::server::certname')), + target => $target, + job => $job, + labels => $labels, + } +} diff --git a/site-modules/profile/manifests/prometheus/node.pp b/site-modules/profile/manifests/prometheus/node.pp new file mode 100644 index 00000000..983e3d01 --- /dev/null +++ b/site-modules/profile/manifests/prometheus/node.pp @@ -0,0 +1,51 @@ +# Prometheus configuration for nodes +class profile::prometheus::node { + include profile::prometheus::apt_config + + $defaults_file = '/etc/default/prometheus-node-exporter' + + package {'prometheus-node-exporter': + ensure => latest, + notify => Service['prometheus-node-exporter'], + } + + service {'prometheus-node-exporter': + ensure => 'running', + enable => true, + require => [ + Package['prometheus-node-exporter'], + File[$defaults_file], + ] + } + + $lookup_defaults_config = lookup('prometheus::node::defaults_config', Hash) + $listen_network = lookup('prometheus::node::listen_network', Optional[String], 'first', undef) + $listen_address = lookup('prometheus::node::listen_address', Optional[String], 'first', undef) + $actual_listen_address = pick($listen_address, ip_for_network($listen_network)) + $listen_port = lookup('prometheus::node::listen_port') + $target = "${actual_listen_address}:${listen_port}" + + $defaults_config = deep_merge( + $lookup_defaults_config, + { + web => { + listen_address => $target, + }, + } + ) + + # Uses $defaults_config + file {$defaults_file: + ensure => 'present', + owner => 'root', + group => 'root', + mode => '0644', + content => template('profile/prometheus/node/prometheus-node-exporter.defaults.erb'), + require => Package['prometheus-node-exporter'], + notify => Service['prometheus-node-exporter'], + } + + profile::prometheus::export_scrape_config {'node': + target => $target, + } +} diff --git a/site-modules/profile/manifests/prometheus/scrape_config.pp b/site-modules/profile/manifests/prometheus/scrape_config.pp new file mode 100644 index 00000000..314fdaef --- /dev/null +++ b/site-modules/profile/manifests/prometheus/scrape_config.pp @@ -0,0 +1,26 @@ +# Scrape configuration for a prometheus exporter +define profile::prometheus::scrape_config ( + String $prometheus_server, + String $target, + String $job, + Hash[String, String] $labels = {}, + +){ + $directory = $profile::prometheus::server::scrape_configs_dir + file {"${directory}/${name}.yaml": + ensure => 'present', + owner => 'root', + group => 'root', + mode => '0644', + content => inline_yaml( + [ + { + targets => [$target], + labels => { + job => $job, + } + $labels, + }, + ] + ), + } +} diff --git a/site-modules/profile/manifests/prometheus/server.pp b/site-modules/profile/manifests/prometheus/server.pp new file mode 100644 index 00000000..78142217 --- /dev/null +++ b/site-modules/profile/manifests/prometheus/server.pp @@ -0,0 +1,109 @@ +# Configure the Prometheus server +class profile::prometheus::server { + include profile::prometheus::apt_config + + $config_dir = '/etc/prometheus' + $config_file = "${config_dir}/prometheus.yml" + $defaults_file = '/etc/default/prometheus' + $scrape_configs_dirname = 'exported-configs' + $scrape_configs_dir = "${config_dir}/${scrape_configs_dirname}" + + $global_config = lookup('prometheus::server::config::global', Hash) + $rule_files = [] + $scrape_configs = [] + $remote_read = [] + $remote_write = [] + $alert_relabel_configs = [] + $alertmanagers = [] + + $full_config = { + global => $global_config, + rule_files => $rule_files, + scrape_configs => $scrape_configs + [ + { + job_name => 'exported', + file_sd_configs => [ + { + files => [ + "${scrape_configs_dirname}/*.yaml", + ] + }, + ] + }, + ], + alerting => { + alert_relabel_configs => $alert_relabel_configs, + alertmanagers => $alertmanagers, + }, + remote_read => $remote_read, + remote_write => $remote_write, + } + + $lookup_defaults_config = lookup('prometheus::server::defaults_config', Hash) + $listen_network = lookup('prometheus::server::listen_network', Optional[String], 'first', undef) + $listen_address = lookup('prometheus::server::listen_address', Optional[String], 'first', undef) + $actual_listen_address = pick($listen_address, ip_for_network($listen_network)) + $listen_port = lookup('prometheus::server::listen_port') + $target = "${actual_listen_address}:${listen_port}" + + $defaults_config = deep_merge( + $lookup_defaults_config, + { + web => { + listen_address => $target, + }, + } + ) + + profile::prometheus::export_scrape_config {'prometheus': + target => $target, + } + + package {'prometheus': + ensure => latest, + notify => Service['prometheus'], + } + + service {'prometheus': + ensure => 'running', + enable => true, + require => [ + Package['prometheus'], + File[$config_file], + File[$defaults_file] + ], + } + + file {$config_file: + ensure => 'present', + owner => 'root', + group => 'root', + mode => '0644', + require => Package['prometheus'], + notify => Service['prometheus'], + content => inline_yaml($full_config), + } + + file {$scrape_configs_dir: + ensure => 'directory', + owner => 'root', + group => 'root', + mode => '0644', + require => Package['prometheus'], + recurse => true, + purge => true, + } + + # Uses $defaults_config + file {$defaults_file: + ensure => 'present', + owner => 'root', + group => 'root', + mode => '0644', + content => template('profile/prometheus/server/prometheus.defaults.erb'), + require => Package['prometheus'], + notify => Service['prometheus'], + } + + Profile::Prometheus::Scrape_config <<| prometheus_server == $trusted['certname'] |>> +} diff --git a/site-modules/profile/manifests/prometheus/sql.pp b/site-modules/profile/manifests/prometheus/sql.pp new file mode 100644 index 00000000..4e025074 --- /dev/null +++ b/site-modules/profile/manifests/prometheus/sql.pp @@ -0,0 +1,90 @@ +# Deployment of prometheus SQL exporter + +class profile::prometheus::sql { + $exporter_name = 'sql' + $package_name = "prometheus-${exporter_name}-exporter" + $service_name = $package_name + $defaults_file = "/etc/default/${package_name}" + $config_file = "/etc/${package_name}.yml" + $config_template = "${config_file}.in" + $config_updater = "/usr/bin/update-${package_name}-config" + + package {$package_name: + ensure => latest, + } + + service {$service_name: + ensure => 'running', + enable => true, + require => [ + Package[$package_name], + Exec[$config_updater], + ] + } + + + file {$config_updater: + ensure => present, + owner => 'root', + group => 'root', + mode => '0755', + source => 'puppet:///modules/profile/prometheus/sql/update-prometheus-sql-exporter-config', + } + + # needed for the the configuration generation + # optiona extra configuration per host + $extra_config = lookup('prometheus::sql::exporter::extra_config', Data, 'first', undef) + + file {$config_template: + ensure => present, + owner => 'root', + group => 'root', + mode => '0644', + content => template('profile/prometheus/sql/prometheus-sql-exporter.yml.in.erb'), + notify => Exec[$config_updater], + } + + $update_deps = ['python3-pkg-resources', 'python3-yaml'] + ensure_packages( + $update_deps, { + ensure => present + }, + ) + + exec {$config_updater: + refreshonly => true, + creates => $config_file, + require => [ + Package[$update_deps], + File[$config_template], + File[$config_updater], + ], + notify => Service[$service_name], + } + + $listen_network = lookup('prometheus::sql::listen_network', Optional[String], 'first', undef) + $listen_address = lookup('prometheus::sql::listen_address', Optional[String], 'first', undef) + $actual_listen_address = pick($listen_address, ip_for_network($listen_network)) + $listen_port = lookup('prometheus::sql::listen_port') + $target = "${actual_listen_address}:${listen_port}" + + $defaults_config = { + web => { + listen_address => $target, + }, + } + + file {$defaults_file: + ensure => present, + owner => 'root', + group => 'root', + mode => '0644', + content => template('profile/prometheus/sql/prometheus-sql-exporter.defaults.erb'), + require => Package[$package_name], + notify => Service[$service_name], + } + + profile::prometheus::export_scrape_config {'sql': + target => $target, + } +} diff --git a/site-modules/profile/manifests/puppet/agent.pp b/site-modules/profile/manifests/puppet/agent.pp new file mode 100644 index 00000000..a6eb399b --- /dev/null +++ b/site-modules/profile/manifests/puppet/agent.pp @@ -0,0 +1,8 @@ +# Puppet agent profile +class profile::puppet::agent { + include ::profile::puppet::base + + class { '::puppet': + * => $::profile::puppet::base::agent_config, + } +} diff --git a/site-modules/profile/manifests/puppet/base.pp b/site-modules/profile/manifests/puppet/base.pp new file mode 100644 index 00000000..28cd22c6 --- /dev/null +++ b/site-modules/profile/manifests/puppet/base.pp @@ -0,0 +1,57 @@ +# Base puppet configuration for all hosts. + +class profile::puppet::base { + $puppetmaster = lookup('puppet::master::hostname') + + $agent_config = { + runmode => 'none', + pluginsync => true, + puppetmaster => $puppetmaster, + additional_settings => { + environment_data_provider => 'hiera', + }, + } + + file { '/usr/local/sbin/swh-puppet-test': + ensure => 'file', + owner => 'root', + group => 'root', + mode => '0755', + content => template('profile/puppet/swh-puppet-test.sh.erb'), + } + + file { '/usr/local/sbin/swh-puppet-apply': + ensure => 'file', + owner => 'root', + group => 'root', + mode => '0755', + content => template('profile/puppet/swh-puppet-apply.sh.erb'), + } + + # Backported packages + if $::lsbdistcodename == 'stretch' { + $pinned_packages = [ + 'facter', + 'libfacter*', + 'libleatherman*', + 'libleatherman-data', + 'libcpp-hocon*', + ] + } + else { + $pinned_packages = undef + } + + if $pinned_packages { + ::apt::pin {'puppet': + explanation => 'Pin puppet dependencies to backports', + codename => "${::lsbdistcodename}-backports", + packages => $pinned_packages, + priority => 990, + } + } else { + ::apt::pin {'puppet': + ensure => 'absent', + } + } +} diff --git a/site-modules/profile/manifests/puppet/master.pp b/site-modules/profile/manifests/puppet/master.pp new file mode 100644 index 00000000..74edf56d --- /dev/null +++ b/site-modules/profile/manifests/puppet/master.pp @@ -0,0 +1,29 @@ +# Puppet master profile +class profile::puppet::master { + $puppetdb = lookup('puppet::master::puppetdb') + + include ::profile::puppet::base + + class { '::puppet': + server => true, + server_common_modules_path => '', + server_environments => [], + server_external_nodes => '', + server_foreman => false, + server_passenger => true, + server_puppetdb_host => $puppetdb, + server_reports => 'store,puppetdb', + server_storeconfigs_backend => 'puppetdb', + + * => $::profile::puppet::base::agent_config, + } + + file { '/usr/local/sbin/swh-puppet-master-deploy': + ensure => 'file', + owner => 'root', + group => 'root', + mode => '0755', + content => template('profile/puppet/swh-puppet-master-deploy.sh.erb'), + } + +} diff --git a/site-modules/profile/manifests/rabbitmq.pp b/site-modules/profile/manifests/rabbitmq.pp new file mode 100644 index 00000000..a689f1cc --- /dev/null +++ b/site-modules/profile/manifests/rabbitmq.pp @@ -0,0 +1,34 @@ +class profile::rabbitmq { + include ::profile::munin::plugins::rabbitmq + + $rabbitmq_user = lookup('rabbitmq::monitoring::user') + $rabbitmq_password = lookup('rabbitmq::monitoring::password') + + package {'rabbitmq-server': + ensure => installed + } + + service {'rabbitmq-server': + ensure => 'running', + enable => true, + require => Package['rabbitmq-server'], + } + + $icinga_checks_file = '/etc/icinga2/conf.d/exported-checks.conf' + + @@::icinga2::object::service {"rabbitmq-server on ${::fqdn}": + service_name => 'rabbitmq server', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'rabbitmq_server', + vars => { + rabbitmq_port => 15672, + rabbitmq_vhost => '/', + rabbitmq_node => $::hostname, + rabbitmq_user => $rabbitmq_user, + rabbitmq_password => $rabbitmq_password, + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } +} diff --git a/site-modules/profile/manifests/resolv_conf.pp b/site-modules/profile/manifests/resolv_conf.pp new file mode 100644 index 00000000..c4202e96 --- /dev/null +++ b/site-modules/profile/manifests/resolv_conf.pp @@ -0,0 +1,10 @@ +# Configure resolv.conf +class profile::resolv_conf { + $nameservers = lookup('dns::nameservers') + $search_domains = lookup('dns::search_domains') + + class {'::resolv_conf': + nameservers => $nameservers, + searchpath => $search_domains, + } +} diff --git a/site-modules/profile/manifests/rsyslog.pp b/site-modules/profile/manifests/rsyslog.pp new file mode 100644 index 00000000..e5fcf325 --- /dev/null +++ b/site-modules/profile/manifests/rsyslog.pp @@ -0,0 +1,11 @@ +# Parameters for rsyslog +class profile::rsyslog { + + file_line {'rsyslog maxsize': + path => '/etc/logrotate.d/rsyslog', + match => 'maxsize 100M', + line => ' maxsize 100M', + after => 'weekly', + } + +} diff --git a/site-modules/profile/manifests/ssh/server.pp b/site-modules/profile/manifests/ssh/server.pp new file mode 100644 index 00000000..0b3b524a --- /dev/null +++ b/site-modules/profile/manifests/ssh/server.pp @@ -0,0 +1,49 @@ +# Configure the SSH server + +class profile::ssh::server { + $sshd_port = lookup('ssh::port') + $sshd_permitrootlogin = lookup('ssh::permitrootlogin') + + class { '::ssh::server': + storeconfigs_enabled => false, + options => { + 'PermitRootLogin' => $sshd_permitrootlogin, + 'Port' => $sshd_port, + }, + } + + $users = lookup('users', Hash, 'deep') + + each($users) |$name, $data| { + if $name == 'root' { + $home = '/root' + } else { + $home = "/home/${name}" + } + + file { "${home}/.ssh": + ensure => directory, + owner => $name, + group => $name, + mode => '0600', + require => [ + User[$name], + File[$home], + ], + } + + if $data['authorized_keys'] { + each($data['authorized_keys']) |$nick, $key| { + ssh_authorized_key { "${name} ${nick}": + ensure => 'present', + user => $name, + key => $key['key'], + type => $key['type'], + require => File["${home}/.ssh"], + } + } + } + } + + +} diff --git a/site-modules/profile/manifests/ssl.pp b/site-modules/profile/manifests/ssl.pp new file mode 100644 index 00000000..fe3f63c2 --- /dev/null +++ b/site-modules/profile/manifests/ssl.pp @@ -0,0 +1,58 @@ +# Deploy SSL certificates +class profile::ssl { + $public_dir = '/etc/ssl/certs/softwareheritage' + $private_dir = '/etc/ssl/private/softwareheritage' + + $ssl_certificates = lookup('ssl', Hash, 'deep') + + $cert_domains = keys($ssl_certificates) + + # Generate {'foo' => "${public_dir}/foo.crt"} from ['foo'] + $certificate_paths = hash(flatten(zip($cert_domains, prefix(suffix($cert_domains, '.crt'), "${public_dir}/")))) + $chain_paths = hash(flatten(zip($cert_domains, prefix(suffix($cert_domains, '.chain'), "${public_dir}/")))) + $private_key_paths = hash(flatten(zip($cert_domains, prefix(suffix($cert_domains, '.key'), "${private_dir}/")))) + + file {$public_dir: + ensure => 'directory', + purge => true, + recurse => true, + owner => 'root', + group => 'root', + mode => '0644', + } + + file {$private_dir: + ensure => 'directory', + purge => true, + recurse => true, + owner => 'root', + group => 'root', + mode => '0600', + } + + each($ssl_certificates) |$domain, $data| { + file {$certificate_paths[$domain]: + ensure => present, + owner => 'root', + group => 'root', + mode => '0644', + content => $data['certificate'], + } + + file {$chain_paths[$domain]: + ensure => present, + owner => 'root', + group => 'root', + mode => '0644', + content => $data['ca_bundle'], + } + + file {$private_key_paths[$domain]: + ensure => present, + owner => 'root', + group => 'root', + mode => '0600', + content => $data['private_key'], + } + } +} diff --git a/site-modules/profile/manifests/swh.pp b/site-modules/profile/manifests/swh.pp new file mode 100644 index 00000000..b8dbcbd3 --- /dev/null +++ b/site-modules/profile/manifests/swh.pp @@ -0,0 +1,41 @@ +# Base class for Software Heritage-specific configuration + +class profile::swh { + $swh_base_directory = lookup('swh::base_directory') + $swh_conf_directory = lookup('swh::conf_directory') + $swh_global_conf_file = lookup('swh::global_conf::file') + $swh_global_conf_contents = lookup('swh::global_conf::contents') + $swh_log_directory = lookup('swh::log_directory') + + $swh_logrotate_conf = '/etc/logrotate.d/softwareheritage' + + file {[ + $swh_base_directory, + $swh_conf_directory, + $swh_log_directory, + ]: + ensure => directory, + owner => 'root', + group => 'root', + mode => '0755', + } + + file {$swh_global_conf_file: + ensure => 'file', + owner => 'root', + group => 'root', + mode => '0644', + content => $swh_global_conf_contents, + } + + file {$swh_logrotate_conf: + ensure => file, + owner => 'root', + group => 'root', + mode => '0644', + content => template('profile/swh/logrotate.conf.erb'), + } + + include profile::swh::deploy + include profile::swh::apt_config +} diff --git a/site-modules/profile/manifests/swh/apt_config.pp b/site-modules/profile/manifests/swh/apt_config.pp new file mode 100644 index 00000000..4d1055a1 --- /dev/null +++ b/site-modules/profile/manifests/swh/apt_config.pp @@ -0,0 +1,75 @@ +# Base class for Software Heritage-specific apt configuration + +class profile::swh::apt_config { + $debian_mirror = lookup('swh::apt_config::debian_mirror') + $debian_security_mirror = lookup('swh::apt_config::debian_security_mirror') + $debian_enable_non_free = lookup('swh::apt_config::enable_non_free') + + class {'::apt': + purge => { + 'sources.list' => true, + 'sources.list.d' => false, + 'preferences' => true, + 'preferences.d' => true, + }, + } + + package {'apt-transport-https': + ensure => 'present', + } + + if lookup('swh::apt_config::unattended_upgrades') { + include profile::swh::apt_config::unattended_upgrades + } + + $repos = $debian_enable_non_free ? { + true => 'main contrib non-free', + default => 'main', + } + + ::apt::source {'debian': + location => $debian_mirror, + release => $::lsbdistcodename, + repos => $repos, + } + + ::apt::source {'debian-updates': + location => $debian_mirror, + release => "${::lsbdistcodename}-updates", + repos => $repos, + } + + ::apt::source {'debian-security': + location => $debian_security_mirror, + release => "${::lsbdistcodename}/updates", + repos => $repos, + } + + if $::lsbdistcodename == 'stretch' { + class {'::apt::backports': + pin => 100, + location => $debian_mirror, + repos => $repos, + } + } else { + ::apt::source {'backports': + ensure => absent, + } + } + + $swh_repository = lookup('swh::apt_config::swh_repository') + $swh_release = $::lsbdistcodename ? { + 'buster' => 'sid', + default => "${::lsbdistcodename}-swh", + } + + ::apt::source {'softwareheritage': + comment => 'Software Heritage specific package repository', + location => $swh_repository, + release => $swh_release, + repos => 'main', + allow_unsigned => true, + } + + Package['apt-transport-https'] -> Class['apt::update'] -> Package <| title != 'apt-transport-https' |> +} diff --git a/site-modules/profile/manifests/swh/apt_config/unattended_upgrades.pp b/site-modules/profile/manifests/swh/apt_config/unattended_upgrades.pp new file mode 100644 index 00000000..220cf153 --- /dev/null +++ b/site-modules/profile/manifests/swh/apt_config/unattended_upgrades.pp @@ -0,0 +1,11 @@ +# Unattended upgrades configuration +class profile::swh::apt_config::unattended_upgrades { + $origins = lookup('swh::apt_config::unattended_upgraes::origins') + + class {'::unattended_upgrades': + mail => { + to => 'root', + }, + origins => $origins, + } +} diff --git a/site-modules/profile/manifests/swh/deploy.pp b/site-modules/profile/manifests/swh/deploy.pp new file mode 100644 index 00000000..6ef5f6fa --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy.pp @@ -0,0 +1,40 @@ +# Deployment of the deployment private key for Software Heritage + +class profile::swh::deploy { + $deploy_group = lookup('swh::deploy::group') + $deploy_directory = lookup('swh::deploy::directory') + + file {$deploy_directory: + ensure => directory, + owner => 'root', + group => $deploy_group, + mode => '0750', + require => [ + Group[$deploy_group], + ] + } + + file {"${deploy_directory}/id_rsa": + ensure => present, + content => lookup('swh::deploy::private_key'), + owner => 'root', + group => $deploy_group, + mode => '0640', + require => [ + File[$deploy_directory], + Group[$deploy_group], + ], + } + + file {"${deploy_directory}/id_rsa.pub": + ensure => present, + content => lookup('swh::deploy::public_key'), + owner => 'root', + group => $deploy_group, + mode => '0640', + require => [ + File[$deploy_directory], + Group[$deploy_group], + ], + } +} diff --git a/site-modules/profile/manifests/swh/deploy/archiver.pp b/site-modules/profile/manifests/swh/deploy/archiver.pp new file mode 100644 index 00000000..ff2a715a --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/archiver.pp @@ -0,0 +1,21 @@ +# Archiver base configuration + +class profile::swh::deploy::archiver { + include ::profile::swh::deploy::objstorage_cloud + + $config_dir = lookup('swh::deploy::worker::swh_storage_archiver::conf_directory') + + file {$config_dir: + ensure => 'directory', + owner => 'swhworker', + group => 'swhworker', + mode => '0644', + } + + $packages = ['python3-swh.archiver'] + + package {$packages: + ensure => 'installed', + } + +} diff --git a/site-modules/profile/manifests/swh/deploy/archiver_content_updater.pp b/site-modules/profile/manifests/swh/deploy/archiver_content_updater.pp new file mode 100644 index 00000000..a1035837 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/archiver_content_updater.pp @@ -0,0 +1,36 @@ +# Deployment of the swh.storage.archiver.updater + +class profile::swh::deploy::archiver_content_updater { + include profile::swh::deploy::archiver + + $conf_file = lookup('swh::deploy::archiver_content_updater::conf_file') + $user = lookup('swh::deploy::archiver_content_updater::user') + $group = lookup('swh::deploy::archiver_content_updater::group') + + $content_updater_config = lookup('swh::deploy::archiver_content_updater::config') + + $service_name = 'swh-archiver-content-updater' + $unit_name = "${service_name}.service" + + file {$conf_file: + ensure => present, + owner => 'root', + group => $group, + mode => '0640', + content => inline_template("<%= @content_updater_config.to_yaml %>\n"), + notify => Service[$service_name], + } + + # Template uses variables + # - $user + # - $group + # + ::systemd::unit_file {$unit_name: + ensure => present, + content => template('profile/swh/deploy/archiver/swh-content-updater.service.erb'), + } ~> service {$service_name: + ensure => running, + enable => false, + require => File[$conf_file], + } +} diff --git a/site-modules/profile/manifests/swh/deploy/base_lister.pp b/site-modules/profile/manifests/swh/deploy/base_lister.pp new file mode 100644 index 00000000..349c176f --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/base_lister.pp @@ -0,0 +1,20 @@ +# deployment for the lister package +class profile::swh::deploy::base_lister { + $config_dir = '/etc/softwareheritage/lister' + + # Contains passwords + file {$config_dir: + ensure => 'directory', + owner => 'swhworker', + group => 'swhdev', + mode => '0644', + purge => true, + recurse => true, + } + + $packages = ['python3-swh.lister'] + + package {$packages: + ensure => 'installed', + } +} diff --git a/site-modules/profile/manifests/swh/deploy/base_loader_git.pp b/site-modules/profile/manifests/swh/deploy/base_loader_git.pp new file mode 100644 index 00000000..51258674 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/base_loader_git.pp @@ -0,0 +1,12 @@ +# Git Loader base configuration + +class profile::swh::deploy::base_loader_git { + include ::profile::swh::deploy::loader + + $packages = ['python3-swh.loader.git'] + + package {$packages: + ensure => 'latest', + } + +} diff --git a/site-modules/profile/manifests/swh/deploy/base_storage.pp b/site-modules/profile/manifests/swh/deploy/base_storage.pp new file mode 100644 index 00000000..93401e27 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/base_storage.pp @@ -0,0 +1,11 @@ +class profile::swh::deploy::base_storage { + $swh_conf_storage_directory = lookup('swh::deploy::storage::conf_directory') + + file {$swh_conf_storage_directory: + ensure => directory, + owner => 'root', + group => 'root', + mode => '0755', + } + +} diff --git a/site-modules/profile/manifests/swh/deploy/base_vault.pp b/site-modules/profile/manifests/swh/deploy/base_vault.pp new file mode 100644 index 00000000..aaeb5ddb --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/base_vault.pp @@ -0,0 +1,16 @@ +class profile::swh::deploy::base_vault { + $conf_directory = lookup('swh::deploy::vault::conf_directory') + + file {$conf_directory: + ensure => directory, + owner => 'root', + group => $group, + mode => '0755', + } + + $packages = ['python3-swh.vault'] + + package {$packages: + ensure => 'present', + } +} diff --git a/site-modules/profile/manifests/swh/deploy/deposit.pp b/site-modules/profile/manifests/swh/deploy/deposit.pp new file mode 100644 index 00000000..6e22abf5 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/deposit.pp @@ -0,0 +1,260 @@ +# Deployment of the swh.deposit server + +class profile::swh::deploy::deposit { + $conf_directory = lookup('swh::deploy::deposit::conf_directory') + + $swh_conf_file = lookup('swh::deploy::deposit::swh_conf_file') + $user = lookup('swh::deploy::deposit::user') + $group = lookup('swh::deploy::deposit::group') + $swh_conf_raw = lookup('swh::deploy::deposit::config') + + $swh_packages = ['python3-swh.deposit'] + + $static_dir = '/usr/lib/python3/dist-packages/swh/deposit/static' + + # private data file to read from swh.deposit.settings.production + $settings_private_data_file = lookup('swh::deploy::deposit::settings_private_data_file') + $settings_private_data = lookup('swh::deploy::deposit::settings_private_data') + + $backend_listen_host = lookup('swh::deploy::deposit::backend::listen::host') + $backend_listen_port = lookup('swh::deploy::deposit::backend::listen::port') + $backend_listen_address = "${backend_listen_host}:${backend_listen_port}" + + $backend_workers = lookup('swh::deploy::deposit::backend::workers') + $backend_http_keepalive = lookup('swh::deploy::deposit::backend::http_keepalive') + $backend_http_timeout = lookup('swh::deploy::deposit::backend::http_timeout') + $backend_reload_mercy = lookup('swh::deploy::deposit::backend::reload_mercy') + + $vhost_name = lookup('swh::deploy::deposit::vhost::name') + $vhost_port = lookup('apache::http_port') + $vhost_aliases = lookup('swh::deploy::deposit::vhost::aliases') + $vhost_docroot = lookup('swh::deploy::deposit::vhost::docroot') + $vhost_basic_auth_file = "${conf_directory}/http_auth" + # swh::deploy::deposit::vhost::basic_auth_content in private + $vhost_basic_auth_content = lookup('swh::deploy::deposit::vhost::basic_auth_content') + $vhost_ssl_port = lookup('apache::https_port') + $vhost_ssl_protocol = lookup('swh::deploy::deposit::vhost::ssl_protocol') + $vhost_ssl_honorcipherorder = lookup('swh::deploy::deposit::vhost::ssl_honorcipherorder') + $vhost_ssl_cipher = lookup('swh::deploy::deposit::vhost::ssl_cipher') + $locked_endpoints = lookup('swh::deploy::deposit::locked_endpoints', Array, 'unique') + + $media_root_directory = lookup('swh::deploy::deposit::media_root_directory') + + include ::gunicorn + + package {$swh_packages: + ensure => latest, + require => Apt::Source['softwareheritage'], + notify => Service['gunicorn-swh-deposit'], + } + + file {$conf_directory: + ensure => directory, + owner => 'root', + group => $group, + mode => '0755', + } + + # swh's configuration part (upload size, etc...) + file {$swh_conf_file: + ensure => present, + owner => 'root', + group => $group, + mode => '0640', + content => inline_template("<%= @swh_conf_raw.to_yaml %>\n"), + notify => Service['gunicorn-swh-deposit'], + } + + file {$media_root_directory: + ensure => directory, + owner => $user, + group => $group, + mode => '2750', + } + + # swh's private configuration part (db, secret key, media_root) + file {$settings_private_data_file: + ensure => present, + owner => 'root', + group => $group, + mode => '0640', + content => inline_template("<%= @settings_private_data.to_yaml %>\n"), + notify => Service['gunicorn-swh-deposit'], + } + + ::gunicorn::instance {'swh-deposit': + ensure => enabled, + user => $user, + group => $group, + executable => 'swh.deposit.wsgi', + settings => { + bind => $backend_listen_address, + workers => $backend_workers, + worker_class => 'sync', + timeout => $backend_http_timeout, + graceful_timeout => $backend_reload_mercy, + keepalive => $backend_http_keepalive, + } + } + + $endpoint_directories = $locked_endpoints.map |$endpoint| { + { path => "^${endpoint}", + provider => 'locationmatch', + auth_type => 'Basic', + auth_name => 'Software Heritage Deposit', + auth_user_file => $vhost_basic_auth_file, + auth_require => 'valid-user', + } + } + + include ::profile::apache::common + include ::apache::mod::proxy + include ::apache::mod::headers + + ::apache::vhost {"${vhost_name}_non-ssl": + servername => $vhost_name, + serveraliases => $vhost_aliases, + port => $vhost_port, + docroot => $vhost_docroot, + proxy_pass => [ + { path => '/static', + url => '!', + }, + { path => '/robots.txt', + url => '!', + }, + { path => '/favicon.ico', + url => '!', + }, + { path => '/', + url => "http://${backend_listen_address}/", + }, + ], + directories => [ + { path => '/1', + provider => 'location', + allow => 'from all', + satisfy => 'Any', + headers => ['add Access-Control-Allow-Origin "*"'], + }, + { path => $static_dir, + options => ['-Indexes'], + }, + ] + $endpoint_directories, + aliases => [ + { alias => '/static', + path => $static_dir, + }, + { alias => '/robots.txt', + path => "${static_dir}/robots.txt", + }, + ], + require => [ + File[$vhost_basic_auth_file], + ] + } + + $ssl_cert_name = 'star_softwareheritage_org' + + include ::profile::hitch + realize(::Profile::Hitch::Ssl_cert[$ssl_cert_name]) + + include ::profile::varnish + ::profile::varnish::vhost {$vhost_name: + aliases => $vhost_aliases, + hsts_max_age => lookup('strict_transport_security::max_age'), + } + + file {$vhost_basic_auth_file: + ensure => present, + owner => 'root', + group => 'www-data', + mode => '0640', + content => $vhost_basic_auth_content, + } + + $icinga_checks_file = '/etc/icinga2/conf.d/exported-checks.conf' + + @@::icinga2::object::service {"swh-deposit api (localhost on ${::fqdn})": + service_name => 'swh-deposit api (localhost)', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + command_endpoint => $::fqdn, + vars => { + http_address => '127.0.0.1', + http_port => $backend_listen_port, + http_uri => '/', + http_string => 'The Software Heritage Deposit', + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + if $backend_listen_host != '127.0.0.1' { + @@::icinga2::object::service {"swh-deposit api (remote on ${::fqdn})": + service_name => 'swh-deposit api (remote)', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_port => $backend_listen_port, + http_uri => '/', + http_string => 'The Software Heritage Deposit', + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + } + + @@::icinga2::object::service {"swh-deposit http redirect on ${::fqdn}": + service_name => 'swh deposit http redirect', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $vhost_name, + http_vhost => $vhost_name, + http_port => $vhost_port, + http_uri => '/', + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + @@::icinga2::object::service {"swh-deposit https on ${::fqdn}": + service_name => 'swh deposit', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $vhost_name, + http_vhost => $vhost_name, + http_port => $vhost_ssl_port, + http_ssl => true, + http_sni => true, + http_uri => '/', + http_onredirect => sticky + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + @@::icinga2::object::service {"swh-deposit https certificate ${::fqdn}": + service_name => 'swh deposit https certificate', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $vhost_name, + http_vhost => $vhost_name, + http_port => $vhost_ssl_port, + http_ssl => true, + http_sni => true, + http_certificate => 60, + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + +} diff --git a/site-modules/profile/manifests/swh/deploy/indexer.pp b/site-modules/profile/manifests/swh/deploy/indexer.pp new file mode 100644 index 00000000..fb59160c --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/indexer.pp @@ -0,0 +1,31 @@ +# Base class for the indexer manifests +class profile::swh::deploy::indexer { + + include ::profile::swh::deploy::objstorage_cloud + + $config_directory = '/etc/softwareheritage/indexer' + $config_file = "${config_directory}/base.yml" + $config = lookup('swh::deploy::worker::swh_indexer::base::config') + + $packages = ['python3-swh.indexer'] + + file {$config_directory: + ensure => 'directory', + owner => 'swhworker', + group => 'swhworker', + mode => '0755', + } + + file {$config_file: + ensure => 'present', + owner => 'swhworker', + group => 'swhdev', + # Contains passwords + mode => '0640', + content => inline_template("<%= @config.to_yaml %>\n"), + } + + package {$packages: + ensure => 'latest', + } +} diff --git a/site-modules/profile/manifests/swh/deploy/indexer_storage.pp b/site-modules/profile/manifests/swh/deploy/indexer_storage.pp new file mode 100644 index 00000000..50c38b8d --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/indexer_storage.pp @@ -0,0 +1,14 @@ +# Deployment of the swh.indexer.storage.api.server + +class profile::swh::deploy::indexer_storage { + include ::profile::swh::deploy::base_storage + + package {'python3-swh.indexer.storage': + ensure => 'latest', + } ~> ::profile::swh::deploy::rpc_server {'indexer-storage': + config_key => 'indexer::storage', + executable => 'swh.indexer.storage.api.server:run_from_webserver', + worker => 'sync', + http_check_string => 'SWH Indexer Storage API server', + } +} diff --git a/site-modules/profile/manifests/swh/deploy/journal.pp b/site-modules/profile/manifests/swh/deploy/journal.pp new file mode 100644 index 00000000..338f947e --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/journal.pp @@ -0,0 +1,18 @@ +# Base Journal configuration + +class profile::swh::deploy::journal { + $conf_directory = lookup('swh::deploy::journal::conf_directory') + + file {$conf_directory: + ensure => 'directory', + owner => 'swhworker', + group => 'swhworker', + mode => '0644', + } + + $package_name = 'python3-swh.journal' + + package {$package_name: + ensure => latest, + } +} diff --git a/site-modules/profile/manifests/swh/deploy/journal_publisher.pp b/site-modules/profile/manifests/swh/deploy/journal_publisher.pp new file mode 100644 index 00000000..8e61e211 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/journal_publisher.pp @@ -0,0 +1,35 @@ +# Deployment of the swh.journal.publisher + +class profile::swh::deploy::journal_publisher { + include ::profile::swh::deploy::journal + + $conf_file = lookup('swh::deploy::journal_publisher::conf_file') + $user = lookup('swh::deploy::journal_publisher::user') + $group = lookup('swh::deploy::journal_publisher::group') + + $publisher_config = lookup('swh::deploy::journal_publisher::config') + + $service_name = 'swh-journal-publisher' + $unit_name = "${service_name}.service" + + file {$conf_file: + ensure => present, + owner => 'root', + group => $group, + mode => '0640', + content => inline_template("<%= @publisher_config.to_yaml %>\n"), + notify => Service[$service_name], + } + + # Template uses variables + # - $user + # - $group + # + ::systemd::unit_file {$unit_name: + ensure => present, + content => template('profile/swh/deploy/journal/swh-journal-publisher.service.erb'), + } ~> service {$service_name: + ensure => running, + enable => false, + } +} diff --git a/site-modules/profile/manifests/swh/deploy/journal_simple_checker_producer.pp b/site-modules/profile/manifests/swh/deploy/journal_simple_checker_producer.pp new file mode 100644 index 00000000..77966383 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/journal_simple_checker_producer.pp @@ -0,0 +1,36 @@ +# Deployment of the swh.journal.checker + +class profile::swh::deploy::journal_simple_checker_producer { + include ::profile::swh::deploy::journal + + $conf_file = lookup('swh::deploy::journal_simple_checker_producer::conf_file') + $user = lookup('swh::deploy::journal_simple_checker_producer::user') + $group = lookup('swh::deploy::journal_simple_checker_producer::group') + + $checker_config = lookup( + 'swh::deploy::journal_simple_checker_producer::config') + + $service_name = 'swh-journal-simple-checker-producer' + $unit_name = "${service_name}.service" + + file {$conf_file: + ensure => present, + owner => 'root', + group => $group, + mode => '0640', + content => inline_template("<%= @checker_config.to_yaml %>\n"), + notify => Service[$service_name], + } + + # Template uses variables + # - $user + # - $group + # + ::systemd::unit {$unit_name: + ensure => present, + content => template('profile/swh/deploy/journal/swh-journal-simple-checker-producer.service.erb'), + } ~> service {$service_name: + ensure => running, + enable => false, + } +} diff --git a/site-modules/profile/manifests/swh/deploy/loader.pp b/site-modules/profile/manifests/swh/deploy/loader.pp new file mode 100644 index 00000000..0ba653b1 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/loader.pp @@ -0,0 +1,11 @@ +# Loader base configuration + +class profile::swh::deploy::loader { + $config_dir = '/etc/softwareheritage/loader' + file {$config_dir: + ensure => 'directory', + owner => 'swhworker', + group => 'swhworker', + mode => '0644', + } +} diff --git a/site-modules/profile/manifests/swh/deploy/objstorage.pp b/site-modules/profile/manifests/swh/deploy/objstorage.pp new file mode 100644 index 00000000..e5daa43b --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/objstorage.pp @@ -0,0 +1,25 @@ +# Deployment of the swh.objstorage.api server + +class profile::swh::deploy::objstorage { + $conf_directory = lookup('swh::deploy::objstorage::conf_directory') + $group = lookup('swh::deploy::objstorage::group') + $swh_packages = ['python3-swh.objstorage'] + + package {$swh_packages: + ensure => latest, + require => Apt::Source['softwareheritage'], + } + Package[$swh_packages] ~> Service['gunicorn-swh-objstorage'] + + file {$conf_directory: + ensure => directory, + owner => 'root', + group => $group, + mode => '0750', + } + + ::profile::swh::deploy::rpc_server {'objstorage': + executable => 'swh.objstorage.api.server:app', + worker => 'async', + } +} diff --git a/site-modules/profile/manifests/swh/deploy/objstorage_archive_notifier_checker.pp b/site-modules/profile/manifests/swh/deploy/objstorage_archive_notifier_checker.pp new file mode 100644 index 00000000..753ef679 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/objstorage_archive_notifier_checker.pp @@ -0,0 +1,42 @@ +# Deployment of the swh.objstorage.checker.ArchiveNotifierContentChecker + +class profile::swh::deploy::objstorage_archive_notifier_checker { + $conf_directory = lookup('swh::deploy::objstorage_archive_notifier_checker::conf_directory') + $conf_file = lookup('swh::deploy::objstorage_archive_notifier_checker::conf_file') + $user = lookup('swh::deploy::objstorage_archive_notifier_checker::user') + $group = lookup('swh::deploy::objstorage_archive_notifier_checker::group') + + # configuration file + $archive_notifier_config = lookup('swh::deploy::objstorage_archive_notifier_checker::config') + + $swh_packages = ['python3-swh.objstorage.checker'] + + package {$swh_packages: + ensure => latest, + require => Apt::Source['softwareheritage'], + } + + file {$conf_directory: + ensure => directory, + owner => 'root', + group => $group, + mode => '0750', + } + + file {$conf_file: + ensure => present, + owner => 'root', + group => $group, + mode => '0640', + content => inline_template("<%= @archive_notifier_config.to_yaml %>\n"), + } + + ::systemd::unit_file {'objstorage_archive_notifier_checker.service': + ensure => present, + content => template('profile/swh/deploy/storage/objstorage_archive_notifier_checker.service.erb'), + require => [ + File[$conf_file], + Package[$swh_packages], + ] + } +} diff --git a/site-modules/profile/manifests/swh/deploy/objstorage_cloud.pp b/site-modules/profile/manifests/swh/deploy/objstorage_cloud.pp new file mode 100644 index 00000000..ae7936a2 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/objstorage_cloud.pp @@ -0,0 +1,17 @@ +# Deployment of the cloud objstorage + +class profile::swh::deploy::objstorage_cloud { + $pinned_packages = [ + 'python3-cffi', + 'python3-cryptography', + 'python3-pkg-resources', + 'python3-pyasn1', + 'python3-setuptools', + ] + + $objstorage_packages = ['python3-swh.objstorage.cloud'] + + package {$objstorage_packages: + ensure => installed, + } +} diff --git a/site-modules/profile/manifests/swh/deploy/objstorage_log_checker.pp b/site-modules/profile/manifests/swh/deploy/objstorage_log_checker.pp new file mode 100644 index 00000000..cd9345e0 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/objstorage_log_checker.pp @@ -0,0 +1,43 @@ +# Deployment of the swh.objstorage.checker.LogContentChecker + +class profile::swh::deploy::objstorage_log_checker { + $conf_directory = lookup('swh::deploy::objstorage_log_checker::conf_directory') + $conf_file = lookup('swh::deploy::objstorage_log_checker::conf_file') + $user = lookup('swh::deploy::objstorage_log_checker::user') + $group = lookup('swh::deploy::objstorage_log_checker::group') + + # configuration file + $log_checker_config = lookup('swh::deploy::objstorage_log_checker::config') + + $swh_packages = ['python3-swh.objstorage.checker'] + + package {$swh_packages: + ensure => latest, + require => Apt::Source['softwareheritage'], + } + + file {$conf_directory: + ensure => directory, + owner => 'root', + group => $group, + mode => '0750', + } + + file {$conf_file: + ensure => present, + owner => 'root', + group => $group, + mode => '0640', + content => inline_template("<%= @log_checker_config.to_yaml %>\n"), + } + + ::systemd::unit_file {'objstorage_log_checker.service': + ensure => present, + content => template('profile/swh/deploy/storage/objstorage_log_checker.service.erb'), + require => [ + File[$conf_file], + Package[$swh_packages], + ] + } + +} diff --git a/site-modules/profile/manifests/swh/deploy/objstorage_repair_checker.pp b/site-modules/profile/manifests/swh/deploy/objstorage_repair_checker.pp new file mode 100644 index 00000000..ef8e7537 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/objstorage_repair_checker.pp @@ -0,0 +1,42 @@ +# Deployment of the swh.objstorage.checker.RepairContentChecker + +class profile::swh::deploy::objstorage_repair_checker { + $conf_directory = lookup('swh::deploy::objstorage_repair_checker::conf_directory') + $conf_file = lookup('swh::deploy::objstorage_repair_checker::conf_file') + $user = lookup('swh::deploy::objstorage_repair_checker::user') + $group = lookup('swh::deploy::objstorage_repair_checker::group') + + $repair_checker_config = lookup('swh::deploy::objstorage_repair_checker::config') + + $swh_packages = ['python3-swh.objstorage.checker'] + + package {$swh_packages: + ensure => latest, + require => Apt::Source['softwareheritage'], + } + + file {$conf_directory: + ensure => directory, + owner => 'root', + group => $group, + mode => '0750', + } + + file {$conf_file: + ensure => present, + owner => 'root', + group => $group, + mode => '0640', + content => inline_template("<%= @repair_checker_config.to_yaml %>\n"), + } + + ::systemd::unit_file {'objstorage_repair_checker.service': + ensure => present, + content => template('profile/swh/deploy/storage/objstorage_repair_checker.service.erb'), + require => [ + File[$conf_file], + Package[$swh_packages], + ] + } + +} diff --git a/site-modules/profile/manifests/swh/deploy/rpc_server.pp b/site-modules/profile/manifests/swh/deploy/rpc_server.pp new file mode 100644 index 00000000..3d158168 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/rpc_server.pp @@ -0,0 +1,141 @@ +# Deploy an instance of a rpc service + +define profile::swh::deploy::rpc_server ( + String $executable, + String $instance_name = $name, + String $config_key = $name, + String $http_check_string = "SWH ${capitalize($name)} API server", + Enum['sync', 'async'] $worker = 'sync', +) { + include ::profile::nginx + + $conf_file = lookup("swh::deploy::${config_key}::conf_file") + $user = lookup("swh::deploy::${config_key}::user") + $group = lookup("swh::deploy::${config_key}::group") + + $service_name = "swh-${instance_name}" + $gunicorn_service_name = "gunicorn-${service_name}" + $gunicorn_unix_socket = "unix:/run/gunicorn/${service_name}/gunicorn.sock" + + $backend_listen_host = lookup("swh::deploy::${config_key}::backend::listen::host") + $backend_listen_port = lookup("swh::deploy::${config_key}::backend::listen::port") + $nginx_server_names = lookup("swh::deploy::${config_key}::backend::server_names") + + $backend_workers = lookup("swh::deploy::${config_key}::backend::workers") + $backend_http_keepalive = lookup("swh::deploy::${config_key}::backend::http_keepalive") + $backend_http_timeout = lookup("swh::deploy::${config_key}::backend::http_timeout") + $backend_reload_mercy = lookup("swh::deploy::${config_key}::backend::reload_mercy") + $backend_max_requests = lookup("swh::deploy::${config_key}::backend::max_requests") + $backend_max_requests_jitter = lookup("swh::deploy::${config_key}::backend::max_requests_jitter") + + $instance_config = lookup("swh::deploy::${config_key}::config") + + include ::gunicorn + + case $worker { + 'sync': { + $gunicorn_worker_class = 'sync' + $nginx_proxy_buffering = 'on' + } + 'async': { + $gunicorn_worker_class = 'aiohttp.worker.GunicornWebWorker' + $nginx_proxy_buffering = 'off' + } + default: { + fail("Worker class ${worker} is unsupported by this module.") + } + } + + file {$conf_file: + ensure => present, + owner => 'root', + group => $group, + mode => '0640', + content => inline_template("<%= @instance_config.to_yaml %>\n"), + notify => Service["gunicorn-swh-${instance_name}"], + } + + ::nginx::resource::upstream {"swh-${instance_name}-gunicorn": + upstream_fail_timeout => 0, + members => [ + $gunicorn_unix_socket, + ], + } + + # Default server on listen_port: return 444 for wrong domain name + ::nginx::resource::server {"nginx-swh-${instance_name}-default": + ensure => present, + listen_ip => $backend_listen_host, + listen_port => $backend_listen_port, + listen_options => 'default_server', + maintenance => true, + maintenance_value => 'return 444', + } + + # actual server + ::nginx::resource::server {"nginx-swh-${instance_name}": + ensure => present, + listen_ip => $backend_listen_host, + listen_port => $backend_listen_port, + listen_options => 'deferred', + server_name => $nginx_server_names, + client_max_body_size => '4G', + proxy => "http://swh-${instance_name}-gunicorn", + proxy_buffering => $nginx_proxy_buffering, + proxy_read_timeout => "${backend_http_timeout}s", + format_log => "combined if=\$error_status", + } + + ::gunicorn::instance {$service_name: + ensure => enabled, + user => $user, + group => $group, + executable => $executable, + settings => { + bind => $gunicorn_unix_socket, + workers => $backend_workers, + worker_class => $gunicorn_worker_class, + timeout => $backend_http_timeout, + graceful_timeout => $backend_reload_mercy, + keepalive => $backend_http_keepalive, + max_requests => $backend_max_requests, + max_requests_jitter => $backend_max_requests_jitter, + }, + } + + $icinga_checks_file = '/etc/icinga2/conf.d/exported-checks.conf' + + @@::icinga2::object::service {"swh-${instance_name} api (localhost on ${::fqdn})": + service_name => "swh-${instance_name} api (localhost)", + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + command_endpoint => $::fqdn, + vars => { + http_address => '127.0.0.1', + http_vhost => '127.0.0.1', + http_port => $backend_listen_port, + http_uri => '/', + http_string => $http_check_string, + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + if $backend_listen_host != '127.0.0.1' { + @@::icinga2::object::service {"swh-${instance_name} api (remote on ${::fqdn})": + service_name => "swh-${instance_name} api (remote)", + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_vhost => $::swh_hostname['internal_fqdn'], + http_port => $backend_listen_port, + http_uri => '/', + http_string => $http_check_string, + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + } +} diff --git a/site-modules/profile/manifests/swh/deploy/scheduler.pp b/site-modules/profile/manifests/swh/deploy/scheduler.pp new file mode 100644 index 00000000..997eebf3 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/scheduler.pp @@ -0,0 +1,161 @@ +# Deployment of swh-scheduler related utilities +class profile::swh::deploy::scheduler { + $conf_file = lookup('swh::deploy::scheduler::conf_file') + $user = lookup('swh::deploy::scheduler::user') + $group = lookup('swh::deploy::scheduler::group') + $database = lookup('swh::deploy::scheduler::database') + + $task_broker = lookup('swh::deploy::scheduler::task_broker') + $task_packages = lookup('swh::deploy::scheduler::task_packages') + $task_modules = lookup('swh::deploy::scheduler::task_modules') + $task_backported_packages = lookup('swh::deploy::scheduler::backported_packages') + + $listener_service_name = 'swh-scheduler-listener' + $listener_unit_name = "${listener_service_name}.service" + $listener_unit_template = "profile/swh/deploy/scheduler/${listener_service_name}.service.erb" + + $runner_service_name = 'swh-scheduler-runner' + $runner_unit_name = "${runner_service_name}.service" + $runner_unit_template = "profile/swh/deploy/scheduler/${runner_service_name}.service.erb" + + $worker_conf_file = '/etc/softwareheritage/worker.ini' + + $packages = ['python3-swh.scheduler'] + $services = [$listener_service_name, $runner_service_name] + + $pinned_packages = $task_backported_packages[$::lsbdistcodename] + if $pinned_packages { + ::apt::pin {'swh-scheduler': + explanation => 'Pin swh.scheduler dependencies to backports', + codename => "${::lsbdistcodename}-backports", + packages => $pinned_packages, + priority => 990, + } + -> package {$task_packages: + ensure => installed, + notify => Service[$runner_service_name], + } + } else { + package {$task_packages: + ensure => installed, + notify => Service[$runner_service_name], + } + } + + package {$packages: + ensure => installed, + notify => Service[$services], + } + + # Template uses variables + # - $database + # + file {$conf_file: + ensure => present, + owner => 'root', + group => $group, + mode => '0640', + content => template('profile/swh/deploy/scheduler/scheduler.ini.erb'), + notify => Service[$services], + } + + # Template uses variables + # - $task_broker + # - $task_modules + # + file {$worker_conf_file: + ensure => present, + owner => 'root', + group => $group, + mode => '0640', + content => template('profile/swh/deploy/scheduler/worker.ini.erb'), + notify => Service[$runner_service_name], + } + + # Template uses variables + # - $user + # - $group + # + ::systemd::unit_file {$listener_unit_name: + ensure => present, + content => template($listener_unit_template), + notify => Service[$listener_service_name], + } + + # Template uses variables + # - $user + # - $group + # + ::systemd::unit_file {$runner_unit_name: + ensure => present, + content => template($runner_unit_template), + notify => Service[$runner_service_name], + } + + service {$runner_service_name: + ensure => running, + enable => true, + require => [ + Package[$packages], + Package[$task_packages], + File[$conf_file], + File[$worker_conf_file], + Systemd::Unit_File[$runner_unit_name], + ], + } + + service {$listener_service_name: + ensure => running, + enable => true, + require => [ + Package[$packages], + File[$conf_file], + File[$worker_conf_file], + Systemd::Unit_File[$listener_unit_name], + ], + } + + # scheduler rpc server + + ::profile::swh::deploy::rpc_server {'scheduler': + config_key => 'scheduler::remote', + executable => 'swh.scheduler.api.server:run_from_webserver', + } + + # task archival cron + + $archive_config_dir = lookup('swh::deploy::scheduler::archive::conf_dir') + $archive_config_file = lookup('swh::deploy::scheduler::archive::conf_file') + $archive_config = lookup('swh::deploy::scheduler::archive::config') + + file {$archive_config_dir: + ensure => 'directory', + owner => $user, + group => 'swhscheduler', + mode => '0644', + } + + file {$archive_config_file: + ensure => present, + owner => 'root', + group => $group, + mode => '0640', + content => inline_template("<%= @archive_config.to_yaml %>\n"), + require => [ + File[$archive_config_dir], + ], + } + + cron {'archive_completed_oneshot_and_disabled_recurring_tasks': + ensure => present, + user => $user, + command => "/usr/bin/python3 -m swh.scheduler.cli task archive", + hour => '*', + minute => fqdn_rand(60, 'archival_tasks_minute'), + require => [ + Package[$packages], + File[$archive_config_file], + ], + } + +} diff --git a/site-modules/profile/manifests/swh/deploy/scheduler_updater.pp b/site-modules/profile/manifests/swh/deploy/scheduler_updater.pp new file mode 100644 index 00000000..0aae812f --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/scheduler_updater.pp @@ -0,0 +1,32 @@ +# Deployment of swh-scheduler-updater related utilities + +class profile::swh::deploy::scheduler_updater { + # Package and backend configuration + $scheduler_updater_packages = ['python3-swh.scheduler.updater'] + + package {$scheduler_updater_packages: + ensure => latest, + } + + $backend_conf_dir = lookup('swh::deploy::scheduler::updater::backend::conf_dir') + $backend_conf_file = lookup('swh::deploy::scheduler::updater::backend::conf_file') + $backend_user = lookup('swh::deploy::scheduler::updater::backend::user') + $backend_group = lookup('swh::deploy::scheduler::updater::backend::group') + $backend_config = lookup('swh::deploy::scheduler::updater::backend::config') + + # file {$backend_conf_dir: + # ensure => directory, + # owner => 'root', + # group => $backend_group, + # mode => '0755', + # } + + file {$backend_conf_file: + ensure => present, + owner => 'root', + group => $backend_group, + mode => '0640', + content => inline_template("<%= @backend_config.to_yaml %>\n"), + } + +} diff --git a/site-modules/profile/manifests/swh/deploy/scheduler_updater_consumer.pp b/site-modules/profile/manifests/swh/deploy/scheduler_updater_consumer.pp new file mode 100644 index 00000000..626f39c0 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/scheduler_updater_consumer.pp @@ -0,0 +1,74 @@ +# Deployment of swh-scheduler-updater related utilities +class profile::swh::deploy::scheduler_updater_consumer { + include ::profile::swh::deploy::scheduler_updater + + # only ghtorrent so far + $consumer_conf_dir = lookup('swh::deploy::scheduler::updater::consumer::ghtorrent::conf_dir') + $consumer_conf_file = lookup('swh::deploy::scheduler::updater::consumer::ghtorrent::conf_file') + $consumer_user = lookup('swh::deploy::scheduler::updater::consumer::user') + $consumer_group = lookup('swh::deploy::scheduler::updater::consumer::group') + + $packages = ['autossh'] + package {$packages: + ensure => present, + } + +# file {$consumer_conf_dir: +# ensure => directory, +# owner => 'root', +# group => $consumer_group, +# mode => '0755', +# } + + $consumer_config = lookup('swh::deploy::scheduler::updater::consumer::ghtorrent::config') + file {$consumer_conf_file: + ensure => present, + owner => 'root', + group => $consumer_group, + mode => '0640', + content => inline_template("<%= @consumer_config.to_yaml %>\n"), + } + + # service needed to forward port locally + + $local_port = lookup('swh::deploy::scheduler::updater::consumer::ghtorrent::port') + $ghtorrent_private_key_raw = lookup('swh::deploy::scheduler::updater::consumer::ghtorrent::private_key') + $ghtorrent_private_key = "/home/${consumer_user}/.ssh/id-rsa-swh-ghtorrent" + + # write private key to access the ghtorrent infra + file {$ghtorrent_private_key: + ensure => present, + owner => $consumer_user, + group => $consumer_group, + mode => '0600', + content => inline_template("<%= @ghtorrent_private_key_raw %>"), + } + + $ghtorrent_service_name = 'ssh-ghtorrent' + $ghtorrent_unit_name = "${ghtorrent_service_name}.service" + # Service to open up the ghtorrent connection infra (no consumption) + ::systemd::unit_file {$ghtorrent_unit_name: + ensure => present, + content => template("profile/swh/deploy/scheduler/${ghtorrent_unit_name}.erb"), + require => Package[$packages], + } ~> service {$ghtorrent_service_name: + ensure => running, + enable => true, + require => File[$ghtorrent_private_key], + } + + # actual service consuming from ghtorrent + + $ghtorrent_consumer_service = 'swh-scheduler-updater-consumer-ghtorrent' + $ghtorrent_consumer_unit_name = "${ghtorrent_consumer_service}.service" + # Service to consume from ghtorrent + ::systemd::unit_file {$ghtorrent_consumer_unit_name: + ensure => present, + content => template("profile/swh/deploy/scheduler/${ghtorrent_consumer_unit_name}.erb"), + } ~> service {$ghtorrent_consumer_service: + ensure => running, + enable => true, + require => Service[$ghtorrent_service_name], + } + +} diff --git a/site-modules/profile/manifests/swh/deploy/scheduler_updater_writer.pp b/site-modules/profile/manifests/swh/deploy/scheduler_updater_writer.pp new file mode 100644 index 00000000..119e2608 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/scheduler_updater_writer.pp @@ -0,0 +1,51 @@ +# Deployment of swh-scheduler-writer related utilities +class profile::swh::deploy::scheduler_updater_writer { + include ::profile::swh::deploy::scheduler_updater + + $writer_conf_dir = lookup('swh::deploy::scheduler::updater::writer::conf_dir') + $writer_conf_file = lookup('swh::deploy::scheduler::updater::writer::conf_file') + $writer_user = lookup('swh::deploy::scheduler::updater::writer::user') + $writer_group = lookup('swh::deploy::scheduler::updater::writer::group') + $writer_config = lookup('swh::deploy::scheduler::updater::writer::config') + +# file {$writer_conf_dir: +# ensure => directory, +# owner => 'root', +# group => $writer_group, +# mode => '0755', +# } + + file {$writer_conf_file: + ensure => present, + owner => 'root', + group => $writer_group, + mode => '0640', + content => inline_template("<%= @writer_config.to_yaml %>\n"), + } + + # unit + timer + $writer_service = 'swh-scheduler-updater-writer' + $writer_unit_name = "${writer_service}.service" + # Service to consume from ghtorrent + ::systemd::unit_file {$writer_unit_name: + ensure => present, + content => template("profile/swh/deploy/scheduler/${writer_unit_name}.erb") + } ~> service {$writer_unit_name: + ensure => stopped, + enable => true, + require => File[$writer_conf_file], + } + + $writer_timer_period = lookup('swh::deploy::scheduler::updater::writer::timer_period') + $writer_timer = 'swh-scheduler-updater-writer' + $writer_timer_unit_name = "${writer_timer}.timer" + ::systemd::unit_file {$writer_timer_unit_name: + ensure => present, + content => template("profile/swh/deploy/scheduler/${writer_timer_unit_name}.erb"), + } ~> service {$writer_timer_unit_name: + ensure => running, + enable => true, + require => Service[$writer_unit_name], + } + +} diff --git a/site-modules/profile/manifests/swh/deploy/storage.pp b/site-modules/profile/manifests/swh/deploy/storage.pp new file mode 100644 index 00000000..f04b7e09 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/storage.pp @@ -0,0 +1,10 @@ +# Deployment of the swh.storage.api server + +class profile::swh::deploy::storage { + include ::profile::swh::deploy::base_storage + + ::profile::swh::deploy::rpc_server {'storage': + executable => 'swh.storage.api.server:run_from_webserver', + worker => 'sync', + } +} diff --git a/site-modules/profile/manifests/swh/deploy/storage_listener.pp b/site-modules/profile/manifests/swh/deploy/storage_listener.pp new file mode 100644 index 00000000..dc5e0250 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/storage_listener.pp @@ -0,0 +1,57 @@ +# Deployment of the swh.storage.listener + +class profile::swh::deploy::storage_listener { + $conf_directory = lookup('swh::deploy::storage_listener::conf_directory') + $conf_file = lookup('swh::deploy::storage_listener::conf_file') + $user = lookup('swh::deploy::storage_listener::user') + $group = lookup('swh::deploy::storage_listener::group') + $database = lookup('swh::deploy::storage_listener::database') + $topic_prefix = lookup('swh::deploy::storage_listener::topic_prefix') + $kafka_brokers = lookup('swh::deploy::storage_listener::kafka_brokers', Array, 'unique') + $poll_timeout = lookup('swh::deploy::storage_listener::poll_timeout') + + $service_name = 'swh-storage-listener' + $unit_name = "${service_name}.service" + + package {'python3-swh.storage.listener': + ensure => latest, + notify => Service[$service_name], + } + + file {$conf_directory: + ensure => directory, + owner => 'root', + group => $group, + mode => '0750', + } + + # Template uses variables + # - $database + # - $kafka_brokers + # - $topic_prefix + # - $poll_timeout + # + file {$conf_file: + ensure => present, + owner => 'root', + group => $group, + mode => '0640', + require => File[$conf_directory], + content => template('profile/swh/deploy/storage_listener/listener.ini.erb'), + notify => Service[$service_name], + } + + # Template uses variables + # - $user + # - $group + # + ::systemd::unit_file {$unit_name: + ensure => present, + content => template('profile/swh/deploy/storage_listener/swh-storage-listener.service.erb'), + require => Package['python3-swh.storage.listener'], + } ~> service {$service_name: + ensure => running, + enable => true, + require => File[$conf_file], + } +} diff --git a/site-modules/profile/manifests/swh/deploy/vault.pp b/site-modules/profile/manifests/swh/deploy/vault.pp new file mode 100644 index 00000000..ae5be6fd --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/vault.pp @@ -0,0 +1,11 @@ +# Deployment of the swh.vault.api server + +class profile::swh::deploy::vault { + include ::profile::swh::deploy::base_vault + Package['python3-swh.vault'] ~> Service['gunicorn-swh-vault'] + + ::profile::swh::deploy::rpc_server {'vault': + executable => 'swh.vault.api.server:make_app_from_configfile()', + worker => 'async', + } +} diff --git a/site-modules/profile/manifests/swh/deploy/webapp.pp b/site-modules/profile/manifests/swh/deploy/webapp.pp new file mode 100644 index 00000000..e014d20d --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/webapp.pp @@ -0,0 +1,227 @@ +# WebApp deployment +class profile::swh::deploy::webapp { + $conf_directory = lookup('swh::deploy::webapp::conf_directory') + $conf_file = lookup('swh::deploy::webapp::conf_file') + $user = lookup('swh::deploy::webapp::user') + $group = lookup('swh::deploy::webapp::group') + + $webapp_config = lookup('swh::deploy::webapp::config') + $conf_log_dir = lookup('swh::deploy::webapp::conf::log_dir') + + $backend_listen_host = lookup('swh::deploy::webapp::backend::listen::host') + $backend_listen_port = lookup('swh::deploy::webapp::backend::listen::port') + $backend_listen_address = "${backend_listen_host}:${backend_listen_port}" + $backend_workers = lookup('swh::deploy::webapp::backend::workers') + $backend_http_keepalive = lookup('swh::deploy::webapp::backend::http_keepalive') + $backend_http_timeout = lookup('swh::deploy::webapp::backend::http_timeout') + $backend_reload_mercy = lookup('swh::deploy::webapp::backend::reload_mercy') + + $swh_packages = ['python3-swh.web'] + $static_dir = '/usr/lib/python3/dist-packages/swh/web/static' + + $varnish_http_port = lookup('varnish::http_port') + + $vhost_name = lookup('swh::deploy::webapp::vhost::name') + $vhost_port = lookup('apache::http_port') + $vhost_aliases = lookup('swh::deploy::webapp::vhost::aliases') + $vhost_docroot = lookup('swh::deploy::webapp::vhost::docroot') + $vhost_basic_auth_file = "${conf_directory}/http_auth" + $vhost_basic_auth_content = lookup('swh::deploy::webapp::vhost::basic_auth_content', String, 'first', '') + $vhost_ssl_port = lookup('apache::https_port') + $vhost_ssl_protocol = lookup('swh::deploy::webapp::vhost::ssl_protocol') + $vhost_ssl_honorcipherorder = lookup('swh::deploy::webapp::vhost::ssl_honorcipherorder') + $vhost_ssl_cipher = lookup('swh::deploy::webapp::vhost::ssl_cipher') + + $locked_endpoints = lookup('swh::deploy::webapp::locked_endpoints', Array, 'unique') + + $endpoint_directories = $locked_endpoints.map |$endpoint| { + { path => "^${endpoint}", + provider => 'locationmatch', + auth_type => 'Basic', + auth_name => 'Software Heritage development', + auth_user_file => $vhost_basic_auth_file, + auth_require => 'valid-user', + } + } + + include ::gunicorn + + package {$swh_packages: + ensure => latest, + require => Apt::Source['softwareheritage'], + notify => Service['gunicorn-swh-webapp'], + } + + file {$conf_directory: + ensure => directory, + owner => 'root', + group => $group, + mode => '0755', + } + + file {$conf_log_dir: + ensure => directory, + owner => 'root', + group => $group, + mode => '0770', + } + + file {$vhost_docroot: + ensure => directory, + owner => 'root', + group => $group, + mode => '0755', + } + + file {$conf_file: + ensure => present, + owner => 'root', + group => $group, + mode => '0640', + content => inline_template("<%= @webapp_config.to_yaml %>\n"), + notify => Service['gunicorn-swh-webapp'], + } + + ::gunicorn::instance {'swh-webapp': + ensure => enabled, + user => $user, + group => $group, + executable => 'swh.web.wsgi:application', + settings => { + bind => $backend_listen_address, + workers => $backend_workers, + worker_class => 'sync', + timeout => $backend_http_timeout, + graceful_timeout => $backend_reload_mercy, + keepalive => $backend_http_keepalive, + } + } + + include ::profile::apache::common + include ::apache::mod::proxy + include ::apache::mod::headers + + ::apache::vhost {"${vhost_name}_non-ssl": + servername => $vhost_name, + serveraliases => $vhost_aliases, + port => $vhost_port, + docroot => $vhost_docroot, + proxy_pass => [ + { path => '/static', + url => '!', + }, + { path => '/robots.txt', + url => '!', + }, + { path => '/favicon.ico', + url => '!', + }, + { path => '/', + url => "http://${backend_listen_address}/", + }, + ], + directories => [ + { path => '/api', + provider => 'location', + allow => 'from all', + satisfy => 'Any', + headers => ['add Access-Control-Allow-Origin "*"'], + }, + { path => $static_dir, + options => ['-Indexes'], + }, + ] + $endpoint_directories, + aliases => [ + { alias => '/static', + path => $static_dir, + }, + { alias => '/robots.txt', + path => "${static_dir}/robots.txt", + }, + ], + require => [ + File[$vhost_basic_auth_file], + ], + } + + $ssl_cert_names = ['star_softwareheritage_org', 'star_internal_softwareheritage_org'] + + include ::profile::hitch + each($ssl_cert_names) |$ssl_cert_name| { + realize(::Profile::Hitch::Ssl_cert[$ssl_cert_name]) + } + + include ::profile::varnish + ::profile::varnish::vhost {$vhost_name: + aliases => $vhost_aliases, + hsts_max_age => lookup('strict_transport_security::max_age'), + } + + if $endpoint_directories { + file {$vhost_basic_auth_file: + ensure => present, + owner => 'root', + group => 'www-data', + mode => '0640', + content => $vhost_basic_auth_content, + } + } else { + file {$vhost_basic_auth_file: + ensure => absent, + } + } + + $icinga_checks_file = '/etc/icinga2/conf.d/exported-checks.conf' + + @@::icinga2::object::service {"swh-webapp http redirect on ${::fqdn}": + service_name => 'swh webapp http redirect', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $vhost_name, + http_vhost => $vhost_name, + http_port => $varnish_http_port, + http_uri => '/', + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + @@::icinga2::object::service {"swh-webapp https on ${::fqdn}": + service_name => 'swh webapp', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $vhost_name, + http_vhost => $vhost_name, + http_port => $vhost_ssl_port, + http_ssl => true, + http_sni => true, + http_uri => '/', + http_onredirect => sticky + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + @@::icinga2::object::service {"swh-webapp https certificate ${::fqdn}": + service_name => 'swh webapp https certificate', + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $vhost_name, + http_vhost => $vhost_name, + http_port => $vhost_ssl_port, + http_ssl => true, + http_sni => true, + http_certificate => 60, + }, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + + include ::profile::swh::deploy::webapp::icinga_checks +} diff --git a/site-modules/profile/manifests/swh/deploy/webapp/icinga_checks.pp b/site-modules/profile/manifests/swh/deploy/webapp/icinga_checks.pp new file mode 100644 index 00000000..2b6b62c0 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/webapp/icinga_checks.pp @@ -0,0 +1,89 @@ +class profile::swh::deploy::webapp::icinga_checks { + $vhost_name = $::profile::swh::deploy::webapp::vhost_name + $vhost_ssl_port = $::profile::swh::deploy::webapp::vhost_ssl_port + $icinga_checks_file = '/etc/icinga2/conf.d/exported-checks.conf' + + $checks = { + 'counters' => { + http_uri => '/api/1/stat/counters/', + http_string => '\"content\":', + }, + 'content known' => { + http_uri => '/api/1/content/known/search/', + http_post => 'q=8624bcdae55baeef00cd11d5dfcfa60f68710a02', + http_string => '\"found\":true', + }, + 'content end to end' => { + http_uri => '/browse/content/4dfc4478b1d5f7388b298fdfc06802485bdeae0c/', + http_string => 'PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2', + }, + 'directory end to end' => { + http_uri => '/browse/directory/977fc4b98c0e85816348cebd3b12026407c368b6/', + http_linespan => true, + http_expect_body_regex => 'Doc.*Grammar.*Include.*Lib.*Mac.*Misc.*Modules.*Objects.*PC.*PCbuild.*LICENSE.*README.rst', + }, + 'revision end to end' => { + http_uri => '/browse/revision/f1b94134a4b879bc55c3dacdb496690c8ebdc03f/', + http_linespan => true, + http_expect_body_regex => join([ + '-:"Allocate the output vlc pictures with dimensions padded,.*', + 'as requested by the decoder \\\\(for alignments\\\\)."' + ]), + }, + 'release end to end' => { + http_uri => '/browse/release/a9b7e3f1eada90250a6b2ab2ef3e0a846cb16831/', + http_linespan => true, + http_expect_body_regex => join([ + '-:"Linux 4.9-rc8.*', + '/revision/3e5de27e940d00d8d504dfb96625fb654f641509/"' + ]), + }, + 'snapshot end to end' => { + http_uri => '/browse/snapshot/baebc2109e4a2ec22a1129a3859647e191d04df4/branches/', + http_linespan => true, + http_expect_body_regex => join([ + '-:"', + join([ + 'buster/main/4.13.13-1', + 'buster/main/4.14.12-2', + 'buster/main/4.14.13-1', + 'buster/main/4.14.17-1', + 'buster/main/4.15.4-1', + 'buster/main/4.9.65-3', + 'experimental/main/4.10~rc6-1~exp2', + 'jessie-backports/main/3.16.39-1', + 'jessie-backports/main/4.7.8-1~bpo8\\\\+1', + 'jessie-backports/main/4.9.18-1~bpo8\\\\+1', + 'jessie-backports/main/4.9.65-3\\\\+deb9u1~bpo8\\\\+1', + 'jessie-backports/main/4.9.65-3\\\\+deb9u2~bpo8\\\\+1', + 'jessie-kfreebsd/main/3.16.7-ckt9-2', + 'jessie-proposed-updates/main/3.16.51-3', + 'jessie-proposed-updates/main/3.16.51-3\\\\+deb8u1', + 'jessie-updates/main/3.16.51-3', + 'jessie/main/3.16.43-1', + 'jessie/main/3.16.51-2', + 'jessie/main/3.16.7-ckt2-1', + 'jessie/main/3.16.7-ckt20-1\\\\+deb8u3', + ], '.*'), + '"', + ]), + } + } + + each($checks) |$name, $args| { + @@::icinga2::object::service {"swh-webapp ${name} ${::fqdn}": + service_name => "swh webapp ${name}", + import => ['generic-service'], + host_name => $::fqdn, + check_command => 'http', + vars => { + http_address => $vhost_name, + http_vhost => $vhost_name, + http_port => $vhost_ssl_port, + http_ssl => true, + } + $args, + target => $icinga_checks_file, + tag => 'icinga2::exported', + } + } +} diff --git a/site-modules/profile/manifests/swh/deploy/worker.pp b/site-modules/profile/manifests/swh/deploy/worker.pp new file mode 100644 index 00000000..2c106ea8 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker.pp @@ -0,0 +1,9 @@ +# Worker deployment +class profile::swh::deploy::worker { + $instances = lookup('swh::deploy::worker::instances') + + each($instances) |$instance| { + $classname = "::profile::swh::deploy::worker::${instance}" + include $classname + } +} diff --git a/site-modules/profile/manifests/swh/deploy/worker/base.pp b/site-modules/profile/manifests/swh/deploy/worker/base.pp new file mode 100644 index 00000000..087867ea --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker/base.pp @@ -0,0 +1,52 @@ +# Base worker profile +class profile::swh::deploy::worker::base { + + include ::systemd::systemctl::daemon_reload + + $systemd_template_unit_name = 'swh-worker@.service' + $systemd_unit_name = 'swh-worker.service' + $systemd_slice_name = 'system-swh\x2dworker.slice' + $systemd_generator = '/lib/systemd/system-generators/swh-worker-generator' + $config_directory = '/etc/softwareheritage/worker' + + package {'python3-swh.scheduler': + ensure => installed, + } + + ::systemd::unit_file {$systemd_template_unit_name: + ensure => 'present', + source => "puppet:///modules/profile/swh/deploy/worker/${systemd_template_unit_name}", + } + + ::systemd::unit_file {$systemd_unit_name: + ensure => 'present', + source => "puppet:///modules/profile/swh/deploy/worker/${systemd_unit_name}", + } ~> service {'swh-worker': + ensure => running, + enable => true, + } + + ::systemd::unit_file {$systemd_slice_name: + ensure => 'present', + source => "puppet:///modules/profile/swh/deploy/worker/${systemd_slice_name}", + } + + file {$systemd_generator: + ensure => 'present', + owner => 'root', + group => 'root', + mode => '0755', + source => 'puppet:///modules/profile/swh/deploy/worker/swh-worker-generator', + notify => Class['systemd::systemctl::daemon_reload'], + } + + file {$config_directory: + ensure => 'directory', + owner => 'swhworker', + group => 'swhdev', + mode => '0644', + purge => true, + recurse => true, + } + +} diff --git a/site-modules/profile/manifests/swh/deploy/worker/instance.pp b/site-modules/profile/manifests/swh/deploy/worker/instance.pp new file mode 100644 index 00000000..b3a60f2f --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker/instance.pp @@ -0,0 +1,68 @@ +# Instance of a worker +define profile::swh::deploy::worker::instance ( + $ensure = present, + $task_broker = '', + $task_modules = [], + $task_queues = [], + $task_soft_time_limit = 0, + $concurrency = 10, + $loglevel = 'info', + $max_tasks_per_child = 5, + $instance_name = $title, + $limit_no_file = undef, + $private_tmp = undef) +{ + include ::profile::swh::deploy::worker::base + + $service_basename = "swh-worker@${instance_name}" + $service_name = "${service_basename}.service" + $config_directory = '/etc/softwareheritage/worker' + $instance_config = "${config_directory}/${instance_name}.ini" + + case $ensure { + 'present', 'running': { + # Uses variables + # - $concurrency + # - $loglevel + # - $max_tasks_per_child + ::systemd::dropin_file {"${service_basename}/parameters.conf": + ensure => present, + unit => $service_name, + filename => 'parameters.conf', + content => template('profile/swh/deploy/worker/parameters.conf.erb'), + } + + # Uses variables + # - $task_broker + # - $task_modules + # - $task_queues + # - $task_soft_time_limit + file {$instance_config: + ensure => present, + owner => 'swhworker', + group => 'swhdev', + # contains a password for the broker + mode => '0640', + content => template('profile/swh/deploy/worker/instance_config.ini.erb'), + } + if $ensure == 'running' { + service {$service_basename: + ensure => $ensure, + require => [ + File[$instance_config], + ], + } + } + } + default: { + file {$instance_config: + ensure => absent, + } + ::systemd::dropin_file {"${service_basename}/parameters.conf": + ensure => absent, + unit => $service_name, + filename => 'parameters.conf', + } + } + } +} diff --git a/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_ctags.pp b/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_ctags.pp new file mode 100644 index 00000000..e5d83eb6 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_ctags.pp @@ -0,0 +1,38 @@ +# Deployment for swh-indexer-ctags + +class profile::swh::deploy::worker::swh_indexer_ctags { + include ::profile::swh::deploy::indexer + + $concurrency = lookup('swh::deploy::worker::swh_indexer::ctags::concurrency') + $loglevel = lookup('swh::deploy::worker::swh_indexer::ctags::loglevel') + $task_broker = lookup('swh::deploy::worker::swh_indexer::ctags::task_broker') + + $config_file = '/etc/softwareheritage/indexer/ctags.yml' + $config = lookup('swh::deploy::worker::swh_indexer::ctags::config') + + $task_modules = ['swh.indexer.tasks'] + $task_queues = ['swh_indexer_content_ctags'] + + Package[$::profile::swh::deploy::indexer::packages] ~> ::profile::swh::deploy::worker::instance {'swh_indexer_ctags': + ensure => present, + concurrency => $concurrency, + loglevel => $loglevel, + task_broker => $task_broker, + task_modules => $task_modules, + task_queues => $task_queues, + require => [ + Class['profile::swh::deploy::indexer'], + Class['profile::swh::deploy::objstorage_cloud'], + File[$config_file], + ], + } + + file {$config_file: + ensure => 'present', + owner => 'swhworker', + group => 'swhdev', + # Contains passwords + mode => '0640', + content => inline_template("<%= @config.to_yaml %>\n"), + } +} diff --git a/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_fossology_license.pp b/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_fossology_license.pp new file mode 100644 index 00000000..66ea9494 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_fossology_license.pp @@ -0,0 +1,38 @@ +# Deployment for swh-indexer-fossology-license + +class profile::swh::deploy::worker::swh_indexer_fossology_license { + include ::profile::swh::deploy::indexer + + $concurrency = lookup('swh::deploy::worker::swh_indexer::fossology_license::concurrency') + $loglevel = lookup('swh::deploy::worker::swh_indexer::fossology_license::loglevel') + $task_broker = lookup('swh::deploy::worker::swh_indexer::fossology_license::task_broker') + + $config_file = '/etc/softwareheritage/indexer/fossology_license.yml' + $config = lookup('swh::deploy::worker::swh_indexer::fossology_license::config') + + $task_modules = ['swh.indexer.tasks'] + $task_queues = ['swh_indexer_content_fossology_license'] + + Package[$::profile::swh::deploy::indexer::packages] ~> ::profile::swh::deploy::worker::instance {'swh_indexer_fossology_license': + ensure => present, + concurrency => $concurrency, + loglevel => $loglevel, + task_broker => $task_broker, + task_modules => $task_modules, + task_queues => $task_queues, + require => [ + Class['profile::swh::deploy::indexer'], + Class['profile::swh::deploy::objstorage_cloud'], + File[$config_file], + ], + } + + file {$config_file: + ensure => 'present', + owner => 'swhworker', + group => 'swhdev', + # Contains passwords + mode => '0640', + content => inline_template("<%= @config.to_yaml %>\n"), + } +} diff --git a/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_language.pp b/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_language.pp new file mode 100644 index 00000000..de4bc02f --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_language.pp @@ -0,0 +1,38 @@ +# Deployment for swh-indexer-language + +class profile::swh::deploy::worker::swh_indexer_language { + include ::profile::swh::deploy::indexer + + $concurrency = lookup('swh::deploy::worker::swh_indexer::language::concurrency') + $loglevel = lookup('swh::deploy::worker::swh_indexer::language::loglevel') + $task_broker = lookup('swh::deploy::worker::swh_indexer::language::task_broker') + + $config_file = '/etc/softwareheritage/indexer/language.yml' + $config = lookup('swh::deploy::worker::swh_indexer::language::config') + + $task_modules = ['swh.indexer.tasks'] + $task_queues = ['swh_indexer_content_language'] + + Package[$::profile::swh::deploy::indexer::packages] ~> ::profile::swh::deploy::worker::instance {'swh_indexer_language': + ensure => present, + concurrency => $concurrency, + loglevel => $loglevel, + task_broker => $task_broker, + task_modules => $task_modules, + task_queues => $task_queues, + require => [ + Class['profile::swh::deploy::indexer'], + Class['profile::swh::deploy::objstorage_cloud'], + File[$config_file], + ], + } + + file {$config_file: + ensure => 'present', + owner => 'swhworker', + group => 'swhdev', + # Contains passwords + mode => '0640', + content => inline_template("<%= @config.to_yaml %>\n"), + } +} diff --git a/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_mimetype.pp b/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_mimetype.pp new file mode 100644 index 00000000..79c001a1 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_mimetype.pp @@ -0,0 +1,38 @@ +# Deployment for swh-indexer-mimetype + +class profile::swh::deploy::worker::swh_indexer_mimetype { + include ::profile::swh::deploy::indexer + + $concurrency = lookup('swh::deploy::worker::swh_indexer::mimetype::concurrency') + $loglevel = lookup('swh::deploy::worker::swh_indexer::mimetype::loglevel') + $task_broker = lookup('swh::deploy::worker::swh_indexer::mimetype::task_broker') + + $config_file = '/etc/softwareheritage/indexer/mimetype.yml' + $config = lookup('swh::deploy::worker::swh_indexer::mimetype::config') + + $task_modules = ['swh.indexer.tasks'] + $task_queues = ['swh_indexer_content_mimetype'] + + Package[$::profile::swh::deploy::indexer::packages] ~> ::profile::swh::deploy::worker::instance {'swh_indexer_mimetype': + ensure => present, + concurrency => $concurrency, + loglevel => $loglevel, + task_broker => $task_broker, + task_modules => $task_modules, + task_queues => $task_queues, + require => [ + Class['profile::swh::deploy::indexer'], + Class['profile::swh::deploy::objstorage_cloud'], + File[$config_file], + ], + } + + file {$config_file: + ensure => 'present', + owner => 'swhworker', + group => 'swhdev', + # Contains passwords + mode => '0640', + content => inline_template("<%= @config.to_yaml %>\n"), + } +} diff --git a/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_orchestrator.pp b/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_orchestrator.pp new file mode 100644 index 00000000..ade2f8ea --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_orchestrator.pp @@ -0,0 +1,37 @@ +# Deployment for swh-indexer + +class profile::swh::deploy::worker::swh_indexer_orchestrator { + + include ::profile::swh::deploy::indexer + + $concurrency = lookup('swh::deploy::worker::swh_indexer::orchestrator::concurrency') + $loglevel = lookup('swh::deploy::worker::swh_indexer::orchestrator::loglevel') + $task_broker = lookup('swh::deploy::worker::swh_indexer::orchestrator::task_broker') + + $config_file = '/etc/softwareheritage/indexer/orchestrator.yml' + $config = lookup('swh::deploy::worker::swh_indexer::orchestrator::config') + + $task_modules = ['swh.indexer.tasks'] + $task_queues = ['swh_indexer_orchestrator_content_all'] + + Package[$::profile::swh::deploy::indexer::packages] ~> ::profile::swh::deploy::worker::instance {'swh_indexer_orchestrator': + ensure => present, + concurrency => $concurrency, + loglevel => $loglevel, + task_broker => $task_broker, + task_modules => $task_modules, + task_queues => $task_queues, + require => [ + Class['profile::swh::deploy::indexer'], + File[$config_file], + ], + } + + file {$config_file: + ensure => 'present', + owner => 'swhworker', + group => 'swhworker', + mode => '0644', + content => inline_template("<%= @config.to_yaml %>\n"), + } +} diff --git a/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_orchestrator_text.pp b/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_orchestrator_text.pp new file mode 100644 index 00000000..a6a288d1 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_orchestrator_text.pp @@ -0,0 +1,37 @@ +# Deployment for swh-indexer + +class profile::swh::deploy::worker::swh_indexer_orchestrator_text { + + include ::profile::swh::deploy::indexer + + $concurrency = lookup('swh::deploy::worker::swh_indexer::orchestrator_text::concurrency') + $loglevel = lookup('swh::deploy::worker::swh_indexer::orchestrator_text::loglevel') + $task_broker = lookup('swh::deploy::worker::swh_indexer::orchestrator_text::task_broker') + + $config_file = '/etc/softwareheritage/indexer/orchestrator_text.yml' + $config = lookup('swh::deploy::worker::swh_indexer::orchestrator_text::config') + + $task_modules = ['swh.indexer.tasks'] + $task_queues = ['swh_indexer_orchestrator_content_text'] + + Package[$::profile::swh::deploy::indexer::packages] ~> ::profile::swh::deploy::worker::instance {'swh_indexer_orchestrator_text': + ensure => present, + concurrency => $concurrency, + loglevel => $loglevel, + task_broker => $task_broker, + task_modules => $task_modules, + task_queues => $task_queues, + require => [ + Class['profile::swh::deploy::indexer'], + File[$config_file], + ], + } + + file {$config_file: + ensure => 'present', + owner => 'swhworker', + group => 'swhworker', + mode => '0644', + content => inline_template("<%= @config.to_yaml %>\n"), + } +} diff --git a/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_rehash.pp b/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_rehash.pp new file mode 100644 index 00000000..ed5d0a1b --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker/swh_indexer_rehash.pp @@ -0,0 +1,38 @@ +# Deployment for swh-indexer-rehash + +class profile::swh::deploy::worker::swh_indexer_rehash { + include ::profile::swh::deploy::indexer + + $concurrency = lookup('swh::deploy::worker::swh_indexer::rehash::concurrency') + $loglevel = lookup('swh::deploy::worker::swh_indexer::rehash::loglevel') + $task_broker = lookup('swh::deploy::worker::swh_indexer::rehash::task_broker') + + $config_file = '/etc/softwareheritage/indexer/rehash.yml' + $config = lookup('swh::deploy::worker::swh_indexer::rehash::config') + + $task_modules = ['swh.indexer.tasks'] + $task_queues = ['swh_indexer_content_rehash'] + + Package[$::profile::swh::deploy::indexer::packages] ~> ::profile::swh::deploy::worker::instance {'swh_indexer_rehash': + ensure => present, + concurrency => $concurrency, + loglevel => $loglevel, + task_broker => $task_broker, + task_modules => $task_modules, + task_queues => $task_queues, + require => [ + Class['profile::swh::deploy::indexer'], + Class['profile::swh::deploy::objstorage_cloud'], + File[$config_file], + ], + } + + file {$config_file: + ensure => 'present', + owner => 'swhworker', + group => 'swhdev', + # Contains passwords + mode => '0640', + content => inline_template("<%= @config.to_yaml %>\n"), + } +} diff --git a/site-modules/profile/manifests/swh/deploy/worker/swh_lister_debian.pp b/site-modules/profile/manifests/swh/deploy/worker/swh_lister_debian.pp new file mode 100644 index 00000000..10992afc --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker/swh_lister_debian.pp @@ -0,0 +1,36 @@ +# Deployment for swh-lister-debian +class profile::swh::deploy::worker::swh_lister_debian { + $concurrency = lookup('swh::deploy::worker::swh_lister_debian::concurrency') + $loglevel = lookup('swh::deploy::worker::swh_lister_debian::loglevel') + $task_broker = lookup('swh::deploy::worker::swh_lister_debian::task_broker') + + $config_file = '/etc/softwareheritage/lister-debian.yml' + $config = lookup('swh::deploy::worker::swh_lister_debian::config', Hash, 'deep') + + $task_modules = ['swh.lister.debian.tasks'] + $task_queues = ['swh_lister_debian'] + + include ::profile::swh::deploy::base_lister + + ::profile::swh::deploy::worker::instance {'swh_lister_debian': + ensure => present, + concurrency => $concurrency, + loglevel => $loglevel, + task_broker => $task_broker, + task_modules => $task_modules, + task_queues => $task_queues, + require => [ + Package['python3-swh.lister'], + File[$config_file], + ], + } + + # Contains passwords + file {$config_file: + ensure => 'present', + owner => 'swhworker', + group => 'swhdev', + mode => '0640', + content => inline_template("<%= @config.to_yaml %>\n"), + } +} diff --git a/site-modules/profile/manifests/swh/deploy/worker/swh_lister_github.pp b/site-modules/profile/manifests/swh/deploy/worker/swh_lister_github.pp new file mode 100644 index 00000000..c33fda29 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker/swh_lister_github.pp @@ -0,0 +1,36 @@ +# Deployment for swh-lister-github +class profile::swh::deploy::worker::swh_lister_github { + $concurrency = lookup('swh::deploy::worker::swh_lister_github::concurrency') + $loglevel = lookup('swh::deploy::worker::swh_lister_github::loglevel') + $task_broker = lookup('swh::deploy::worker::swh_lister_github::task_broker') + + $config_file = '/etc/softwareheritage/lister-github.com.yml' + $config = lookup('swh::deploy::worker::swh_lister_github::config', Hash, 'deep') + + $task_modules = ['swh.lister.github.tasks'] + $task_queues = ['swh_lister_github_discover', 'swh_lister_github_refresh'] + + include ::profile::swh::deploy::base_lister + + ::profile::swh::deploy::worker::instance {'swh_lister_github': + ensure => present, + concurrency => $concurrency, + loglevel => $loglevel, + task_broker => $task_broker, + task_modules => $task_modules, + task_queues => $task_queues, + require => [ + Package['python3-swh.lister'], + File[$config_file], + ], + } + + # Contains passwords + file {$config_file: + ensure => 'present', + owner => 'swhworker', + group => 'swhdev', + mode => '0640', + content => inline_template("<%= @config.to_yaml %>\n"), + } +} diff --git a/site-modules/profile/manifests/swh/deploy/worker/swh_loader_debian.pp b/site-modules/profile/manifests/swh/deploy/worker/swh_loader_debian.pp new file mode 100644 index 00000000..d0e8c8bc --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker/swh_loader_debian.pp @@ -0,0 +1,39 @@ +# Deployment for swh-loader-debian +class profile::swh::deploy::worker::swh_loader_debian { + $concurrency = lookup('swh::deploy::worker::swh_loader_debian::concurrency') + $loglevel = lookup('swh::deploy::worker::swh_loader_debian::loglevel') + $task_broker = lookup('swh::deploy::worker::swh_loader_debian::task_broker') + + $config_file = '/etc/softwareheritage/loader/debian.yml' + $config = lookup('swh::deploy::worker::swh_loader_debian::config') + + $task_modules = ['swh.loader.debian.tasks'] + $task_queues = ['swh_loader_debian'] + + $packages = ['python3-swh.loader.debian'] + + package {$packages: + ensure => 'present', + } + + ::profile::swh::deploy::worker::instance {'swh_loader_debian': + ensure => present, + concurrency => $concurrency, + loglevel => $loglevel, + task_broker => $task_broker, + task_modules => $task_modules, + task_queues => $task_queues, + require => [ + Package[$packages], + File[$config_file], + ], + } + + file {$config_file: + ensure => 'present', + owner => 'swhworker', + group => 'swhworker', + mode => '0644', + content => inline_template("<%= @config.to_yaml %>\n"), + } +} diff --git a/site-modules/profile/manifests/swh/deploy/worker/swh_loader_deposit.pp b/site-modules/profile/manifests/swh/deploy/worker/swh_loader_deposit.pp new file mode 100644 index 00000000..d224c486 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker/swh_loader_deposit.pp @@ -0,0 +1,65 @@ +# Deployment for swh-loader-deposit +class profile::swh::deploy::worker::swh_loader_deposit { + $concurrency = lookup('swh::deploy::worker::swh_loader_deposit::concurrency') + $loglevel = lookup('swh::deploy::worker::swh_loader_deposit::loglevel') + $task_broker = lookup('swh::deploy::worker::swh_loader_deposit::task_broker') + + $deposit_config_directory = lookup('swh::deploy::deposit::conf_directory') + $config_file = lookup('swh::deploy::worker::swh_loader_deposit::swh_conf_file') + $config = lookup('swh::deploy::worker::swh_loader_deposit::config') + + $task_modules = ['swh.deposit.loader.tasks'] + $task_queues = ['swh_checker_deposit', 'swh_loader_deposit'] + + $packages = ['python3-swh.deposit.loader'] + $private_tmp = lookup('swh::deploy::worker::swh_loader_deposit::private_tmp') + + $service_name = 'swh_loader_deposit' + + package {$packages: + ensure => 'latest', + notify => Service["swh-worker@$service_name"], + } + + # This installs the swh-worker@$service_name service + ::profile::swh::deploy::worker::instance {$service_name: + ensure => running, + concurrency => $concurrency, + loglevel => $loglevel, + task_broker => $task_broker, + task_modules => $task_modules, + task_queues => $task_queues, + private_tmp => $private_tmp, + require => [ + Package[$packages], + File[$config_file], + ], + } + + file {$deposit_config_directory: + ensure => directory, + owner => 'swhworker', + group => 'swhdev', + mode => '0750', + } + + file {$config_file: + ensure => 'present', + owner => 'swhworker', + group => 'swhdev', + mode => '0640', + content => inline_template("<%= @config.to_yaml %>\n"), + require => [ + File[$deposit_config_directory], + ], + } + + $swh_client_conf_file = lookup('swh::deploy::deposit::client::swh_conf_file') + $swh_client_config = lookup('swh::deploy::deposit::client::settings_private_data') + file {$swh_client_conf_file: + owner => 'swhworker', + group => 'swhdev', + mode => '0640', + content => inline_template("<%= @swh_client_config.to_yaml %>\n"), + } +} diff --git a/site-modules/profile/manifests/swh/deploy/worker/swh_loader_git.pp b/site-modules/profile/manifests/swh/deploy/worker/swh_loader_git.pp new file mode 100644 index 00000000..595397d9 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker/swh_loader_git.pp @@ -0,0 +1,35 @@ +# Deployment for swh-loader-git (remote) +class profile::swh::deploy::worker::swh_loader_git { + include ::profile::swh::deploy::base_loader_git + + $concurrency = lookup('swh::deploy::worker::swh_loader_git::concurrency') + $loglevel = lookup('swh::deploy::worker::swh_loader_git::loglevel') + $task_broker = lookup('swh::deploy::worker::swh_loader_git::task_broker') + + $config_file = '/etc/softwareheritage/loader/git-updater.yml' + $config = lookup('swh::deploy::worker::swh_loader_git::config') + + $task_modules = ['swh.loader.git.tasks'] + $task_queues = ['swh_loader_git'] + + ::profile::swh::deploy::worker::instance {'swh_loader_git': + ensure => present, + concurrency => $concurrency, + loglevel => $loglevel, + task_broker => $task_broker, + task_modules => $task_modules, + task_queues => $task_queues, + require => [ + Class['profile::swh::deploy::base_loader_git'], + File[$config_file], + ], + } + + file {$config_file: + ensure => 'present', + owner => 'swhworker', + group => 'swhworker', + mode => '0644', + content => inline_template("<%= @config.to_yaml %>\n"), + } +} diff --git a/site-modules/profile/manifests/swh/deploy/worker/swh_loader_git_disk.pp b/site-modules/profile/manifests/swh/deploy/worker/swh_loader_git_disk.pp new file mode 100644 index 00000000..c0d9b971 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker/swh_loader_git_disk.pp @@ -0,0 +1,39 @@ +# Deployment for swh-loader-git (disk) +class profile::swh::deploy::worker::swh_loader_git_disk { + include ::profile::swh::deploy::base_loader_git + + $concurrency = lookup('swh::deploy::worker::swh_loader_git_disk::concurrency') + $loglevel = lookup('swh::deploy::worker::swh_loader_git_disk::loglevel') + $task_broker = lookup('swh::deploy::worker::swh_loader_git_disk::task_broker') + + $config_file = '/etc/softwareheritage/loader/git-loader.yml' + $config = lookup('swh::deploy::worker::swh_loader_git_disk::config') + + $task_modules = ['swh.loader.git.tasks'] + $task_queues = ['swh_loader_git_express', 'swh_loader_git_archive'] + + $service_name = 'swh_loader_git_disk' + + Package[$::profile::swh::deploy::base_loader_git::packages] ~> Service["swh-worker@$service_name"] + + ::profile::swh::deploy::worker::instance {$service_name: + ensure => running, + concurrency => $concurrency, + loglevel => $loglevel, + task_broker => $task_broker, + task_modules => $task_modules, + task_queues => $task_queues, + require => [ + Class['profile::swh::deploy::base_loader_git'], + File[$config_file], + ], + } + + file {$config_file: + ensure => 'present', + owner => 'swhworker', + group => 'swhworker', + mode => '0644', + content => inline_template("<%= @config.to_yaml %>\n"), + } +} diff --git a/site-modules/profile/manifests/swh/deploy/worker/swh_loader_mercurial.pp b/site-modules/profile/manifests/swh/deploy/worker/swh_loader_mercurial.pp new file mode 100644 index 00000000..5cf92187 --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker/swh_loader_mercurial.pp @@ -0,0 +1,45 @@ +# Deployment for swh-loader-mercurial (disk) +class profile::swh::deploy::worker::swh_loader_mercurial { + include ::profile::swh::deploy::base_loader_git + + $concurrency = lookup('swh::deploy::worker::swh_loader_mercurial::concurrency') + $loglevel = lookup('swh::deploy::worker::swh_loader_mercurial::loglevel') + $task_broker = lookup('swh::deploy::worker::swh_loader_mercurial::task_broker') + + $config_file = '/etc/softwareheritage/loader/hg.yml' + $config = lookup('swh::deploy::worker::swh_loader_mercurial::config') + + $task_modules = ['swh.loader.mercurial.tasks'] + $task_queues = ['swh_loader_mercurial', 'swh_loader_mercurial_archive'] + + $service_name = 'swh_loader_mercurial' + $private_tmp = lookup('swh::deploy::worker::swh_loader_mercurial::private_tmp') + + $packages = ['python3-swh.loader.mercurial'] + + package {$packages: + ensure => 'latest', + notify => Service["swh-worker@$service_name"] + } + + ::profile::swh::deploy::worker::instance {$service_name: + ensure => running, + concurrency => $concurrency, + loglevel => $loglevel, + task_broker => $task_broker, + task_modules => $task_modules, + task_queues => $task_queues, + private_tmp => $private_tmp, + require => [ + File[$config_file], + ], + } + + file {$config_file: + ensure => 'present', + owner => 'swhworker', + group => 'swhworker', + mode => '0644', + content => inline_template("<%= @config.to_yaml %>\n"), + } +} diff --git a/site-modules/profile/manifests/swh/deploy/worker/swh_loader_svn.pp b/site-modules/profile/manifests/swh/deploy/worker/swh_loader_svn.pp new file mode 100644 index 00000000..55b94d0f --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker/swh_loader_svn.pp @@ -0,0 +1,43 @@ +# Deployment for swh-loader-svn +class profile::swh::deploy::worker::swh_loader_svn { + $concurrency = lookup('swh::deploy::worker::swh_loader_svn::concurrency') + $loglevel = lookup('swh::deploy::worker::swh_loader_svn::loglevel') + $task_broker = lookup('swh::deploy::worker::swh_loader_svn::task_broker') + + $config_file = '/etc/softwareheritage/loader/svn.yml' + $config = lookup('swh::deploy::worker::swh_loader_svn::config') + + $task_modules = ['swh.loader.svn.tasks'] + $task_queues = ['swh_loader_svn', 'swh_loader_svn_mount_and_load'] + + $packages = ['python3-swh.loader.svn'] + $limit_no_file = lookup('swh::deploy::worker::swh_loader_svn::limit_no_file') + $private_tmp = lookup('swh::deploy::worker::swh_loader_svn::private_tmp') + + package {$packages: + ensure => 'latest', + } + + ::profile::swh::deploy::worker::instance {'swh_loader_svn': + ensure => present, + concurrency => $concurrency, + loglevel => $loglevel, + task_broker => $task_broker, + task_modules => $task_modules, + task_queues => $task_queues, + limit_no_file => $limit_no_file, + private_tmp => $private_tmp, + require => [ + Package[$packages], + File[$config_file], + ], + } + + file {$config_file: + ensure => 'present', + owner => 'swhworker', + group => 'swhworker', + mode => '0644', + content => inline_template("<%= @config.to_yaml %>\n"), + } +} diff --git a/site-modules/profile/manifests/swh/deploy/worker/swh_storage_archiver.pp b/site-modules/profile/manifests/swh/deploy/worker/swh_storage_archiver.pp new file mode 100644 index 00000000..6b11364d --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker/swh_storage_archiver.pp @@ -0,0 +1,37 @@ +# Deployment for swh-storage-archiver +class profile::swh::deploy::worker::swh_storage_archiver { + include ::profile::swh::deploy::archiver + + $concurrency = lookup('swh::deploy::worker::swh_storage_archiver::concurrency') + $max_tasks_per_child = lookup('swh::deploy::worker::swh_storage_archiver::max_tasks_per_child') + $loglevel = lookup('swh::deploy::worker::swh_storage_archiver::loglevel') + $task_broker = lookup('swh::deploy::worker::swh_storage_archiver::task_broker') + + $config_file = lookup('swh::deploy::worker::swh_storage_archiver::conf_file') + $config = lookup('swh::deploy::worker::swh_storage_archiver::config') + + $task_modules = ['swh.archiver.tasks'] + $task_queues = ['swh_storage_archive_worker'] + + ::profile::swh::deploy::worker::instance {'swh_storage_archiver': + ensure => present, + concurrency => $concurrency, + loglevel => $loglevel, + task_broker => $task_broker, + task_modules => $task_modules, + task_queues => $task_queues, + max_tasks_per_child => $max_tasks_per_child, + require => [ + File[$config_file], + ], + } + + file {$config_file: + ensure => 'present', + owner => 'swhworker', + group => 'swhdev', + # Contains passwords + mode => '0640', + content => inline_template("<%= @config.to_yaml %>\n"), + } +} diff --git a/site-modules/profile/manifests/swh/deploy/worker/swh_vault_cooker.pp b/site-modules/profile/manifests/swh/deploy/worker/swh_vault_cooker.pp new file mode 100644 index 00000000..c7d475bf --- /dev/null +++ b/site-modules/profile/manifests/swh/deploy/worker/swh_vault_cooker.pp @@ -0,0 +1,36 @@ +# Deployment of a vault cooker + +class profile::swh::deploy::worker::swh_vault_cooker { + include ::profile::swh::deploy::base_vault + + $concurrency = lookup('swh::deploy::worker::swh_vault_cooker::concurrency') + $loglevel = lookup('swh::deploy::worker::swh_vault_cooker::loglevel') + $task_broker = lookup('swh::deploy::worker::swh_vault_cooker::task_broker') + + $conf_file = lookup('swh::deploy::worker::swh_vault_cooker::conf_file') + $config = lookup('swh::deploy::worker::swh_vault_cooker::config') + + $task_modules = ['swh.vault.cooking_tasks'] + $task_queues = ['swh_vault_cooking', 'swh_vault_batch_cooking'] + + ::profile::swh::deploy::worker::instance {'swh_vault_cooker': + ensure => present, + concurrency => $concurrency, + loglevel => $loglevel, + task_broker => $task_broker, + task_modules => $task_modules, + task_queues => $task_queues, + require => [ + Package[$packages], + File[$conf_file], + ], + } + + file {$conf_file: + ensure => 'present', + owner => 'swhworker', + group => 'swhworker', + mode => '0644', + content => inline_template("<%= @config.to_yaml %>\n"), + } +} diff --git a/site-modules/profile/manifests/systemd_journal.pp b/site-modules/profile/manifests/systemd_journal.pp new file mode 100644 index 00000000..5bee37d6 --- /dev/null +++ b/site-modules/profile/manifests/systemd_journal.pp @@ -0,0 +1,7 @@ +# Manage the configuration of the systemd journal +class profile::systemd_journal { + + include profile::systemd_journal::apt_config + include profile::systemd_journal::base_config + include profile::systemd_journal::journalbeat +} diff --git a/site-modules/profile/manifests/systemd_journal/apt_config.pp b/site-modules/profile/manifests/systemd_journal/apt_config.pp new file mode 100644 index 00000000..42912701 --- /dev/null +++ b/site-modules/profile/manifests/systemd_journal/apt_config.pp @@ -0,0 +1,3 @@ +# Manage the configuration of apt for the systemd journal +class profile::systemd_journal::apt_config { +} diff --git a/site-modules/profile/manifests/systemd_journal/base_config.pp b/site-modules/profile/manifests/systemd_journal/base_config.pp new file mode 100644 index 00000000..e70a9fc7 --- /dev/null +++ b/site-modules/profile/manifests/systemd_journal/base_config.pp @@ -0,0 +1,20 @@ +# Manage systemd-journald base configuration +class profile::systemd_journal::base_config { + file {'/var/log/journal': + ensure => 'directory', + owner => 'root', + group => 'systemd-journal', + mode => '2755', + notify => Exec['systemd_journal-tmpdir'], + } + + exec {'systemd_journal-tmpdir': + command => 'systemd-tmpfiles --create --prefix /var/log/journal', + path => ['/sbin', '/usr/sbin', '/bin', '/usr/bin'], + require => [ + File['/var/log/journal'], + Package['acl'], + ], + unless => 'getfacl -csp /var/log/journal | grep -Eq group:adm:r-x', + } +} diff --git a/site-modules/profile/manifests/systemd_journal/journalbeat.pp b/site-modules/profile/manifests/systemd_journal/journalbeat.pp new file mode 100644 index 00000000..a00b61e5 --- /dev/null +++ b/site-modules/profile/manifests/systemd_journal/journalbeat.pp @@ -0,0 +1,65 @@ +# Journalbeat: a systemd journal collection beater for the ELK stack +class profile::systemd_journal::journalbeat { + $package = 'journalbeat' + $user = 'journalbeat' + $group = 'nogroup' + $homedir = '/var/lib/journalbeat' + $configdir = '/etc/journalbeat' + $configfile = "${configdir}/journalbeat.yml" + $service = 'journalbeat' + + $logstash_hosts = lookup('systemd_journal::logstash_hosts') + + package {$package: + ensure => present + } + + user {$user: + ensure => present, + gid => $group, + groups => 'systemd-journal', + home => $homedir, + managehome => true, + system => true, + } + + # Uses variables + # - $user + # - $homedir + # - $configfile + # + ::systemd::unit_file {"${service}.service": + ensure => present, + content => template('profile/systemd_journal/journalbeat/journalbeat.service.erb'), + } + ~> service {$service: + ensure => running, + enable => true, + require => [ + Package[$package], + File[$configfile], + ], + } + + file {$configdir: + ensure => directory, + owner => 'root', + group => 'root', + mode => '0644', + } + + # Uses variables + # - $logstash_hosts + # + file {$configfile: + ensure => present, + owner => 'root', + group => 'root', + mode => '0644', + content => template('profile/systemd_journal/journalbeat/journalbeat.yml.erb'), + notify => [ + Service[$service], + ], + } + +} diff --git a/site-modules/profile/manifests/unbound.pp b/site-modules/profile/manifests/unbound.pp new file mode 100644 index 00000000..ac34a77a --- /dev/null +++ b/site-modules/profile/manifests/unbound.pp @@ -0,0 +1,94 @@ +# Parameters for the unbound DNS resolver +class profile::unbound { + $has_local_cache = lookup('dns::local_cache') + + $package = 'unbound' + $service = 'unbound' + $conf_dir = '/etc/unbound/unbound.conf.d' + $forwarders_file = "${conf_dir}/forwarders.conf" + $insecure_file = "${conf_dir}/insecure.conf" + $auto_root_data = '/var/lib/unbound/root.key' + + if $has_local_cache { + include ::profile::resolv_conf + + $forwarders = lookup('dns::forwarders') + $forward_zones = lookup('dns::forward_zones') + $insecure = lookup('dns::forwarder_insecure') + + package {$package: + ensure => installed, + } + package {'dns-root-data': + ensure => installed, + } + + service {$service: + ensure => running, + enable => true, + require => [ + Package[$package], + File[$forwarders_file], + File[$auto_root_data], + ], + } + + Service[$service] -> File['/etc/resolv.conf'] + + # uses variables $forwarders, $forward_zones + file {$forwarders_file: + ensure => present, + owner => 'root', + group => 'root', + mode => '0644', + content => template('profile/unbound/forwarders.conf.erb'), + require => Package[$package], + notify => Service[$service], + } + + $insecure_ensure = $insecure ? { + true => present, + default => absent, + } + + file {$insecure_file: + ensure => $insecure_ensure, + owner => 'root', + group => 'root', + mode => '0644', + source => 'puppet:///modules/profile/unbound/insecure.conf', + require => Package[$package], + notify => Service[$service], + } + + file {'/etc/default/unbound': + ensure => present, + owner => 'root', + group => 'root', + mode => '0644', + require => Package[$package], + } + + file {$auto_root_data: + ensure => present, + owner => 'unbound', + group => 'unbound', + mode => '0644', + replace => 'no', + source => '/usr/share/dns/root.key', + require => [ + Package[$package], + Package['dns-root-data'], + ], + } + + file_line {'unbound root auto update': + ensure => present, + path => '/etc/default/unbound', + match => '^ROOT_TRUST_ANCHOR_UPDATE\=', + line => 'ROOT_TRUST_ANCHOR_UPDATE=false', + require => Package[$package], + notify => Service[$service], + } + } +} diff --git a/site-modules/profile/manifests/varnish.pp b/site-modules/profile/manifests/varnish.pp new file mode 100644 index 00000000..8e2e1b34 --- /dev/null +++ b/site-modules/profile/manifests/varnish.pp @@ -0,0 +1,71 @@ +# Varnish configuration + +class profile::varnish { + $includes_dir = '/etc/varnish/includes' + $includes_vcl_name = 'includes.vcl' + $includes_vcl = "/etc/varnish/${includes_vcl_name}" + + $http_port = lookup('varnish::http_port') + $backend_http_port = lookup('varnish::backend_http_port') + + $listen = lookup('varnish::listen') + $admin_listen = lookup('varnish::admin_listen') + $admin_port = lookup('varnish::admin_port') + $http2_support = lookup('varnish::http2_support') + $secret = lookup('varnish::secret') + $storage_type = lookup('varnish::storage_type') + $storage_size = lookup('varnish::storage_size') + $storage_file = lookup('varnish::storage_file') + + if $http2_support { + $runtime_params = { + feature => '+http2', + } + } else { + $runtime_params = {} + } + + class {'::varnish': + addrepo => false, + listen => $listen, + admin_listen => $admin_listen, + admin_port => $admin_port, + secret => $secret, + storage_type => $storage_type, + storage_size => $storage_size, + storage_file => $storage_file, + runtime_params => $runtime_params, + } + + ::varnish::vcl {'/etc/varnish/default.vcl': + content => template('profile/varnish/default.vcl.erb'), + require => Concat[$includes_vcl], + } + + file {$includes_dir: + ensure => directory, + owner => 'root', + group => 'root', + mode => '0644', + require => Class['varnish::install'], + notify => Exec['vcl_reload'], + } + + concat {$includes_vcl: + ensure => present, + owner => 'root', + group => 'root', + mode => '0644', + ensure_newline => true, + require => Class['varnish::install'], + notify => Exec['vcl_reload'], + } + + concat::fragment {"${includes_vcl}:header": + target => $includes_vcl, + content => "# File managed with puppet (module profile::varnish)\n# All modifications will be lost\n\n", + order => '00', + } + + include ::profile::varnish::default_vcls +} diff --git a/site-modules/profile/manifests/varnish/default_vcls.pp b/site-modules/profile/manifests/varnish/default_vcls.pp new file mode 100644 index 00000000..9db8f9ce --- /dev/null +++ b/site-modules/profile/manifests/varnish/default_vcls.pp @@ -0,0 +1,13 @@ +# Default VCLs included with the varnish profile + +class profile::varnish::default_vcls { + ::profile::varnish::vcl_include {'backend_default': + order => '01', + content => template('profile/varnish/backend_default.vcl.erb'), + } + + ::profile::varnish::vcl_include {'synth_redirect': + order => '10', + content => file('profile/varnish/synth_redirect.vcl'), + } +} diff --git a/site-modules/profile/manifests/varnish/vcl_include.pp b/site-modules/profile/manifests/varnish/vcl_include.pp new file mode 100644 index 00000000..6efa7a06 --- /dev/null +++ b/site-modules/profile/manifests/varnish/vcl_include.pp @@ -0,0 +1,24 @@ +# Definition of vcl includes + +define profile::varnish::vcl_include ( + String $content, + String $basename = $title, + String $order = '01', +) { + $includes_dir = $::profile::varnish::includes_dir + $includes_vcl = $::profile::varnish::includes_vcl + + $vcl_path = "${::profile::varnish::includes_dir}/${order}_${basename}.vcl" + + ::varnish::vcl {$vcl_path: + content => $content, + require => File[$includes_dir], + } + + concat::fragment {"${includes_vcl}:${basename}": + target => $includes_vcl, + content => "include \"includes/${order}_${basename}.vcl\";", + order => $order, + require => ::Varnish::Vcl[$vcl_path], + } +} diff --git a/site-modules/profile/manifests/varnish/vhost.pp b/site-modules/profile/manifests/varnish/vhost.pp new file mode 100644 index 00000000..6b9baef5 --- /dev/null +++ b/site-modules/profile/manifests/varnish/vhost.pp @@ -0,0 +1,15 @@ +# Virtual host definition for varnish + +define profile::varnish::vhost ( + String $servername = $title, + String $order = '50', + Array[String] $aliases = [], + Optional[String] $vcl_recv_extra = undef, + Optional[String] $vcl_deliver_extra = undef, + Variant[Undef, String, Integer[1]] $hsts_max_age = undef, +) { + ::profile::varnish::vcl_include {"vhost_${servername}": + order => $order, + content => template('profile/varnish/vhost.vcl.erb'), + } +} diff --git a/site-modules/profile/manifests/zookeeper.pp b/site-modules/profile/manifests/zookeeper.pp new file mode 100644 index 00000000..7591f997 --- /dev/null +++ b/site-modules/profile/manifests/zookeeper.pp @@ -0,0 +1,11 @@ +# Zookeeper cluster member profile + +class profile::zookeeper { + class {'::zookeeper': + servers => lookup('zookeeper::servers', Hash), + datastore => lookup('zookeeper::datastore'), + client_port => lookup('zookeeper::client_port'), + election_port => lookup('zookeeper::election_port'), + leader_port => lookup('zookeeper::leader_port'), + } +} diff --git a/site-modules/profile/metadata.json b/site-modules/profile/metadata.json new file mode 100644 index 00000000..3bbfc315 --- /dev/null +++ b/site-modules/profile/metadata.json @@ -0,0 +1,14 @@ +{ + "name": "swh-profile", + "version": "0.1.0", + "author": "swh", + "summary": "Software Heritage Puppet Profiles", + "license": "Apache 2.0", + "source": "git@git.softwareheritage.org:swh/sysadm/puppet/swh-profile", + "project_page": null, + "issues_url": null, + "dependencies": [ + {"name":"puppetlabs-stdlib","version_requirement":">= 1.0.0"} + ] +} + diff --git a/site-modules/profile/spec/classes/init_spec.rb b/site-modules/profile/spec/classes/init_spec.rb new file mode 100644 index 00000000..02d70706 --- /dev/null +++ b/site-modules/profile/spec/classes/init_spec.rb @@ -0,0 +1,7 @@ +require 'spec_helper' +describe 'profile' do + + context 'with defaults for all parameters' do + it { should contain_class('profile') } + end +end diff --git a/site-modules/profile/spec/spec_helper.rb b/site-modules/profile/spec/spec_helper.rb new file mode 100644 index 00000000..2c6f5664 --- /dev/null +++ b/site-modules/profile/spec/spec_helper.rb @@ -0,0 +1 @@ +require 'puppetlabs_spec_helper/module_spec_helper' diff --git a/site-modules/profile/templates/desktop/printers/MFP_Paris.ppd.erb b/site-modules/profile/templates/desktop/printers/MFP_Paris.ppd.erb new file mode 100644 index 00000000..3a400aae --- /dev/null +++ b/site-modules/profile/templates/desktop/printers/MFP_Paris.ppd.erb @@ -0,0 +1,3999 @@ +*PPD-Adobe: "4.3" +*% Adobe Systems PostScript(R) Printer Description File +*% Copyright (c) 2010-2013 TOSHIBA TEC Corporation +*% +*% This software is free software; you can redistribute it and/or +*% modify it under the terms of the GNU General Public License as +*% published by the Free Software Foundation; either version 2 of +*% the License, or (at your option) any later version. +*% +*% In addition to the permissions in the GNU General Public License, +*% TOSHIBA TEC Corporation gives you unlimited permission to link the +*% PostScript code fragments herein into your PostScript documents to +*% form an executable for enabling printer-specific features, and +*% distribute those combinations without any restrictions from the use +*% of this PPD file. (The General Public License restrictions do apply +*% in other respects; for example, they cover modification of the +*% file, and distribution when not merged into a PostScript document.) +*% +*% This software is distributed in the hope that it will be useful, +*% but WITHOUT ANY WARRANTY; without even the implied warranty of +*% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +*% GNU General Public License for more details. +*% +*% You should have received a copy of the GNU General Public +*% License along with this software; if not, write to the Free +*% Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, +*% MA 02111 USA +*% +*% Date: 01 November 2013" + +*FormatVersion: "4.3" + +*FileVersion: "7.22" + +*LanguageEncoding: ISOLatin1 +*LanguageVersion: English +*PCFileName: "TSES6D_1.PPD" + +*Manufacturer: "TOSHIBA" + +*Product: "(TOSHIBA e-STUDIO6570C)" +*Product: "(TOSHIBA e-STUDIO6560C)" +*Product: "(TOSHIBA e-STUDIO5560C)" +*Product: "(TOSHIBA e-STUDIO6550C)" +*Product: "(TOSHIBA e-STUDIO6540C)" +*Product: "(TOSHIBA e-STUDIO5540C)" +*Product: "(TOSHIBA e-STUDIO4540C)" +*Product: "(TOSHIBA e-STUDIO3540C)" +*Product: "(TOSHIBA e-STUDIO3040C)" +*Product: "(TOSHIBA e-STUDIO2540C)" +*Product: "(TOSHIBA e-STUDIO2040C)" +*Product: "(TOSHIBA e-STUDIO2550C)" +*Product: "(TOSHIBA e-STUDIO2050C)" +*Product: "(TOSHIBA e-STUDIO2055C)" +*Product: "(TOSHIBA e-STUDIO2555C)" +*Product: "(TOSHIBA e-STUDIO3055C)" +*Product: "(TOSHIBA e-STUDIO3555C)" +*Product: "(TOSHIBA e-STUDIO4555C)" +*Product: "(TOSHIBA e-STUDIO5055C)" +*Product: "(TOSHIBA e-STUDIO287CS)" +*Product: "(TOSHIBA e-STUDIO347CS)" +*Product: "(TOSHIBA e-STUDIO407CS)" + +*PSVersion: "(3010) 1" + +*ModelName: "TOSHIBA ColorMFP" + +*NickName: "TOSHIBA ColorMFP" + +*ShortNickName: "TOSHIBA ColorMFP" + +*cupsFilter: "application/vnd.cups-postscript 0 <%= @ppd_auth_filter -%>" + + +*% ===== Installable Option ========================== +*OpenGroup: InstallableOptions/Options Installed + +*OpenUI *ModelSelection/Model Selection: PickOne +*DefaultModelSelection: e-STUDIO6550CSeries +*ModelSelection e-STUDIO6570CSeries/TOSHIBA e-STUDIO6570CSeries: "" +*ModelSelection e-STUDIO6550CSeries/TOSHIBA e-STUDIO6550CSeries: "" +*ModelSelection e-STUDIO5055CSeries/TOSHIBA e-STUDIO5055CSeries: "" +*ModelSelection e-STUDIO4540CSeries/TOSHIBA e-STUDIO4540CSeries: "" +*ModelSelection e-STUDIO2550CSeries/TOSHIBA e-STUDIO2550CSeries: "" +*ModelSelection e-STUDIO407CSeries/TOSHIBA e-STUDIO407CS Series: "" +*CloseUI: *ModelSelection + +*OpenUI *Finisher/Finisher: PickOne +*DefaultFinisher: None +*Finisher None/Not Installed: "" +*Finisher Staple1/Hanging Finisher: "" +*Finisher InnerFinisher1/Inner Finisher (1 Tray): "" +*Finisher InnerFinisher2/Inner Finisher (2 Trays): "" +*Finisher StapleM/Saddle Stitch Finisher: "" +*Finisher StapleMH/Saddle Stitch Finisher and Hole Punch: "" +*CloseUI: *Finisher + +*OpenUI *Pedestal/Drawers: PickOne +*DefaultPedestal: Drawer1234 +*Pedestal Drawer1/Drawer 1: "" +*Pedestal Drawer1L/Drawer 1 & LCF: "" +*Pedestal Drawer12/Drawer 1 & Drawer 2: "" +*Pedestal Drawer12L/Drawer 1,2 & LCF: "" +*Pedestal Drawer123/Drawer 1,2 & Drawer 3: "" +*Pedestal Drawer1234/Drawer 1,2 & Drawer 3,4: "" +*CloseUI: *Pedestal + +*OpenUI *ExternalLCF/External LCF: PickOne +*DefaultExternalLCF: None +*ExternalLCF None/Not Installed: "" +*ExternalLCF Installed/Installed: "" +*CloseUI: *ExternalLCF + +*OpenUI *HardDisk/Harddisk: Boolean +*DefaultHardDisk: True +*HardDisk False/Not Installed: "" +*HardDisk True/Installed: "" +*CloseUI: *HardDisk + +*CloseGroup: InstallableOptions + + +*% ===== User Interface Constaints ===================== + +*% UIConstraints are handled differently on CUPS. +*% Therefore, there cannot be any UIConstraints against +*% feature defaults. Certain UIConstraints have been +*% commented out rather than deleted to document the +*% constraints that are supported in OS9 and CUPS Panther. + +*% ===== Installable options === +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *Finisher Staple1 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *Finisher InnerFinisher1 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *Finisher InnerFinisher2 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *Pedestal Drawer1 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *Pedestal Drawer1L +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *Pedestal Drawer12 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *Pedestal Drawer123 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *HardDisk False + +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *Finisher Staple1 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *Finisher InnerFinisher1 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *Finisher InnerFinisher2 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *Pedestal Drawer1 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *Pedestal Drawer1L +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *Pedestal Drawer12 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *Pedestal Drawer123 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *HardDisk False + +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *Finisher Staple1 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *Finisher InnerFinisher1 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *Pedestal Drawer1 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *Pedestal Drawer1L +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *ExternalLCF Installed +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *HardDisk False + +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *Finisher InnerFinisher1 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *Finisher InnerFinisher2 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *Pedestal Drawer1 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *Pedestal Drawer1L +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *ExternalLCF Installed +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *HardDisk False + +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *Finisher Staple1 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *Finisher InnerFinisher1 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *Pedestal Drawer1L +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *ExternalLCF Installed + +*UIConstraints: *ModelSelection e-STUDIO407CSeries *Finisher Staple1 +*UIConstraints: *ModelSelection e-STUDIO407CSeries *Finisher InnerFinisher2 +*UIConstraints: *ModelSelection e-STUDIO407CSeries *Finisher StapleM +*UIConstraints: *ModelSelection e-STUDIO407CSeries *Finisher StapleMH +*UIConstraints: *ModelSelection e-STUDIO407CSeries *ExternalLCF Installed +*UIConstraints: *ModelSelection e-STUDIO407CSeries *HardDisk False + +*% ===== Page sizes ============ +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *PageSize LG135 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *PageSize IndexCard +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *PageSize Executive +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *PageSize Env9 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *PageSize Env10 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *PageSize EnvMonarch +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *PageSize EnvPRC5 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *PageSize EnvChou3 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *PageSize EnvChou4 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *PageSize EnvYou4 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *PageSize EnvC5 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *PageSize DoublePostcardRotated +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *BookletPaperSize Executive +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *BookletPaperSize LG135 + +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *PageSize LG135 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *PageSize IndexCard +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *PageSize Executive +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *PageSize Env9 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *PageSize Env10 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *PageSize EnvMonarch +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *PageSize EnvPRC5 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *PageSize EnvChou3 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *PageSize EnvChou4 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *PageSize EnvYou4 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *PageSize EnvC5 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *PageSize DoublePostcardRotated +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *BookletPaperSize Executive +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *BookletPaperSize LG135 + +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *PageSize LG135 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *PageSize IndexCard +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *PageSize Executive +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *PageSize 1319inch +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *PageSize Env9 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *PageSize EnvChou4 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *PageSize EnvC5 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *PageSize DoublePostcardRotated +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *BookletPaperSize Executive +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *BookletPaperSize LG135 + +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *PageSize LG135 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *PageSize IndexCard +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *PageSize Executive +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *PageSize 1319inch +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *PageSize Env9 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *PageSize Env10 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *PageSize EnvMonarch +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *PageSize EnvPRC5 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *PageSize EnvChou3 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *PageSize EnvChou4 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *PageSize EnvYou4 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *PageSize EnvC5 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *PageSize DoublePostcardRotated +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *BookletPaperSize Executive +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *BookletPaperSize LG135 + +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *PageSize LG135 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *PageSize IndexCard +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *PageSize Executive +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *PageSize 1319inch +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *PageSize A3-Wide +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *PageSize 320450mm +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *PageSize 320460mm +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *PageSize Ledger-Wide +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *PageSize Env9 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *PageSize EnvChou4 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *PageSize EnvC5 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *PageSize DoublePostcardRotated +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *BookletPaperSize Executive +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *BookletPaperSize LG135 + +*UIConstraints: *ModelSelection e-STUDIO407CSeries *PageSize 1319inch +*UIConstraints: *ModelSelection e-STUDIO407CSeries *PageSize A3 +*UIConstraints: *ModelSelection e-STUDIO407CSeries *PageSize A3-Wide +*UIConstraints: *ModelSelection e-STUDIO407CSeries *PageSize 320450mm +*UIConstraints: *ModelSelection e-STUDIO407CSeries *PageSize 320460mm +*UIConstraints: *ModelSelection e-STUDIO407CSeries *PageSize Ledger-Wide +*UIConstraints: *ModelSelection e-STUDIO407CSeries *PageSize 8K +*UIConstraints: *ModelSelection e-STUDIO407CSeries *PageSize Ledger +*UIConstraints: *ModelSelection e-STUDIO407CSeries *PageSize Computer +*UIConstraints: *ModelSelection e-STUDIO407CSeries *PageSize B4 +*UIConstraints: *ModelSelection e-STUDIO407CSeries *BookletPaperSize Ledger +*UIConstraints: *ModelSelection e-STUDIO407CSeries *BookletPaperSize A3 +*UIConstraints: *ModelSelection e-STUDIO407CSeries *BookletPaperSize B4 +*UIConstraints: *ModelSelection e-STUDIO407CSeries *BookletPaperSize Computer +*UIConstraints: *ModelSelection e-STUDIO407CSeries *BookletPaperSize 8K + +*% ===== Input / Media types === +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType Plain +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType Plainthin +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType Special3 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType Special3back +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType Special4 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType Special5 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType Special6 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType Thin +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType Thinback +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType Plainback +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType Recycledback +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType Thick5 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType Envelope +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType Envelopeback +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType Envelope1 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType Envelope2 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType Envelope3 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType Envelope4 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType UserType1 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType UserType2 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType UserType3 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType UserType4 +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *MediaType UserType5 + +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType Plain +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType Plainthin +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType Special3 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType Special3back +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType Special4 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType Special5 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType Special6 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType Thin +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType Thinback +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType Plainback +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType Recycledback +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType Thick5 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType Envelope +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType Envelopeback +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType Envelope1 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType Envelope2 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType Envelope3 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType Envelope4 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType UserType1 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType UserType2 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType UserType3 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType UserType4 +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *MediaType UserType5 + +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *MediaType PlainA +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *MediaType Plainthin +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *MediaType Plain1 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *MediaType Plain2 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *MediaType Special4 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *MediaType Special5 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *MediaType Special6 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *MediaType Thick5 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *MediaType Envelope1 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *MediaType Envelope2 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *MediaType Envelope3 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *MediaType Envelope4 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *MediaType UserType1 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *MediaType UserType2 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *MediaType UserType3 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *MediaType UserType4 +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *MediaType UserType5 + +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType PlainA +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType Plainthin +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType Plain1 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType Plain2 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType Special3 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType Special3back +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType Special4 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType Special5 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType Special6 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType Thin +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType Thinback +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType Plainback +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType Recycledback +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType Thick5 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType Envelope +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType Envelopeback +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType Envelope1 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType Envelope2 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType Envelope3 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType Envelope4 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType UserType1 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType UserType2 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType UserType3 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType UserType4 +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *MediaType UserType5 + +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType PlainA +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType Plainthin +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType Plain1 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType Plain2 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType Thick3 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType Thick3back +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType Thick4 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType Thick4back +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType Special3 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType Special3back +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType Special4 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType Special5 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType Special6 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType Thin +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType Thinback +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType Thick5 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType Envelope1 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType Envelope2 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType Envelope3 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType Envelope4 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType UserType1 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType UserType2 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType UserType3 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType UserType4 +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *MediaType UserType5 + +*UIConstraints: *ModelSelection e-STUDIO407CSeries *MediaType PlainA +*UIConstraints: *ModelSelection e-STUDIO407CSeries *MediaType Plain1 +*UIConstraints: *ModelSelection e-STUDIO407CSeries *MediaType Plain2 +*UIConstraints: *ModelSelection e-STUDIO407CSeries *MediaType Thick1back +*UIConstraints: *ModelSelection e-STUDIO407CSeries *MediaType Thick2back +*UIConstraints: *ModelSelection e-STUDIO407CSeries *MediaType Thick3back +*UIConstraints: *ModelSelection e-STUDIO407CSeries *MediaType Thick4back +*UIConstraints: *ModelSelection e-STUDIO407CSeries *MediaType Recycled +*UIConstraints: *ModelSelection e-STUDIO407CSeries *MediaType Recycledback +*UIConstraints: *ModelSelection e-STUDIO407CSeries *MediaType Special1back +*UIConstraints: *ModelSelection e-STUDIO407CSeries *MediaType Special2back +*UIConstraints: *ModelSelection e-STUDIO407CSeries *MediaType Special3back +*UIConstraints: *ModelSelection e-STUDIO407CSeries *MediaType Transparency +*UIConstraints: *ModelSelection e-STUDIO407CSeries *MediaType Tab +*UIConstraints: *ModelSelection e-STUDIO407CSeries *MediaType Thin +*UIConstraints: *ModelSelection e-STUDIO407CSeries *MediaType Thinback +*UIConstraints: *ModelSelection e-STUDIO407CSeries *MediaType Plainback +*UIConstraints: *ModelSelection e-STUDIO407CSeries *MediaType Envelope +*UIConstraints: *ModelSelection e-STUDIO407CSeries *MediaType Envelopeback + +*% ===== Resolution ============ + +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *Resolution 600x1200dpi + +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *Resolution 600x1200dpi + +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *Resolution 1200dpi + +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *Resolution 600x1200dpi +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *Resolution 1200dpi + +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *Resolution 1200dpi + +*UIConstraints: *ModelSelection e-STUDIO407CSeries *Resolution 1200dpi + +*% ===== Finishing ============= + +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *OutputTray Inner + +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *OutputTray Inner + +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *OutputTray InnerU +*UIConstraints: *ModelSelection e-STUDIO5055CSeries *OutputTray SideExitTray + +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *OutputTray InnerU +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *OutputTray SideExitTray + +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *OutputTray InnerU +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *OutputTray SideExitTray +*UIConstraints: *ModelSelection e-STUDIO2550CSeries *Folding True + +*UIConstraints: *ModelSelection e-STUDIO407CSeries *OutputTray InnerU +*UIConstraints: *ModelSelection e-STUDIO407CSeries *OutputTray SideExitTray +*UIConstraints: *ModelSelection e-STUDIO407CSeries *OutputTray Bin2 +*UIConstraints: *ModelSelection e-STUDIO407CSeries *Folding True + +*% ===== Auto Trapping ========= + +*UIConstraints: *ModelSelection e-STUDIO6570CSeries *AutoTrapping True +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *AutoTrapping True +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *AutoTrapping True + +*% ===== Red Seal Color Mode === + +*UIConstraints: *ModelSelection e-STUDIO6550CSeries *RedSealColorMode True +*UIConstraints: *ModelSelection e-STUDIO4540CSeries *RedSealColorMode True +*UIConstraints: *ModelSelection e-STUDIO407CSeries *RedSealColorMode True + +*% ===== End of Model Constraints ============ + +*% ===== Red Seal Color Mode Constraints ===== + +*UIConstraints: *ImageType Photo *RedSealColorMode True +*UIConstraints: *ImageType Presentation *RedSealColorMode True +*UIConstraints: *ImageType LineArt *RedSealColorMode True + +*UIConstraints: *RedSealColorMode True *ImageType Photo +*UIConstraints: *RedSealColorMode True *ImageType Presentation +*UIConstraints: *RedSealColorMode True *ImageType LineArt + +*% ===== Auto Trapping Constraints ===== + +*UIConstraints: *Resolution 1200dpi *AutoTrapping True +*UIConstraints: *Resolution 600x1200dpi *AutoTrapping True +*UIConstraints: *ColorType Mono *AutoTrapping True +*UIConstraints: *ColorType Black&Red *AutoTrapping True +*UIConstraints: *ColorType Black&Green *AutoTrapping True +*UIConstraints: *ColorType Black&Blue *AutoTrapping True +*UIConstraints: *ColorType Black&Cyan *AutoTrapping True +*UIConstraints: *ColorType Black&Magenta *AutoTrapping True +*UIConstraints: *ColorType Black&Yellow *AutoTrapping True +*UIConstraints: *ColorType Black&White *AutoTrapping True + +*UIConstraints: *AutoTrapping True *Resolution 1200dpi +*UIConstraints: *AutoTrapping True *Resolution 600x1200dpi +*UIConstraints: *AutoTrapping True *ColorType Mono +*UIConstraints: *AutoTrapping True *ColorType Black&Red +*UIConstraints: *AutoTrapping True *ColorType Black&Green +*UIConstraints: *AutoTrapping True *ColorType Black&Blue +*UIConstraints: *AutoTrapping True *ColorType Black&Cyan +*UIConstraints: *AutoTrapping True *ColorType Black&Magenta +*UIConstraints: *AutoTrapping True *ColorType Black&Yellow +*UIConstraints: *AutoTrapping True *ColorType Black&White + +*UIConstraints: *PostScriptOverprint True *AutoTrapping True +*UIConstraints: *AutoTrapping True *PostScriptOverprint True + +*% ===== Finisher Constraints ===== + +*UIConstraints: *Finisher None *OutputTray Bin1 +*UIConstraints: *Finisher None *OutputTray Bin2 +*UIConstraints: *Finisher None *Stapling UL +*UIConstraints: *Finisher None *Stapling ML +*UIConstraints: *Finisher None *Stapling LL +*UIConstraints: *Finisher None *Stapling UR +*UIConstraints: *Finisher None *Stapling MR +*UIConstraints: *Finisher None *Stapling LR +*UIConstraints: *Finisher None *Stapling MT +*UIConstraints: *Finisher None *Stapling MB +*UIConstraints: *Finisher None *Stapling SS + +*UIConstraints: *Finisher Staple1 *OutputTray Bin2 +*UIConstraints: *Finisher Staple1 *Stapling ML +*UIConstraints: *Finisher Staple1 *Stapling LL +*UIConstraints: *Finisher Staple1 *Stapling UR +*UIConstraints: *Finisher Staple1 *Stapling MR +*UIConstraints: *Finisher Staple1 *Stapling LR +*UIConstraints: *Finisher Staple1 *Stapling MT +*UIConstraints: *Finisher Staple1 *Stapling MB +*UIConstraints: *Finisher Staple1 *Stapling SS + +*UIConstraints: *Finisher None *HolePunch LEP-0R +*UIConstraints: *Finisher None *HolePunch SEP-0R +*UIConstraints: *Finisher None *HolePunch LEP-180R +*UIConstraints: *Finisher None *HolePunch SEP-180R + +*UIConstraints: *Finisher StapleM *HolePunch LEP-0R +*UIConstraints: *Finisher StapleM *HolePunch SEP-0R +*UIConstraints: *Finisher StapleM *HolePunch LEP-180R +*UIConstraints: *Finisher StapleM *HolePunch SEP-180R + +*UIConstraints: *Finisher Staple1 *HolePunch LEP-0R +*UIConstraints: *Finisher Staple1 *HolePunch SEP-0R +*UIConstraints: *Finisher Staple1 *HolePunch LEP-180R +*UIConstraints: *Finisher Staple1 *HolePunch SEP-180R + +*UIConstraints: *Finisher InnerFinisher1 *HolePunch LEP-0R +*UIConstraints: *Finisher InnerFinisher1 *HolePunch SEP-0R +*UIConstraints: *Finisher InnerFinisher1 *HolePunch LEP-180R +*UIConstraints: *Finisher InnerFinisher1 *HolePunch SEP-180R +*UIConstraints: *Finisher InnerFinisher1 *Stapling ML +*UIConstraints: *Finisher InnerFinisher1 *Stapling LL +*UIConstraints: *Finisher InnerFinisher1 *Stapling UR +*UIConstraints: *Finisher InnerFinisher1 *Stapling MR +*UIConstraints: *Finisher InnerFinisher1 *Stapling LR +*UIConstraints: *Finisher InnerFinisher1 *Stapling MT +*UIConstraints: *Finisher InnerFinisher1 *Stapling MB +*UIConstraints: *Finisher InnerFinisher1 *Stapling SS + +*UIConstraints: *OutputTray Inner *Stapling UL +*UIConstraints: *OutputTray Inner *Stapling ML +*UIConstraints: *OutputTray Inner *Stapling LL +*UIConstraints: *OutputTray Inner *Stapling UR +*UIConstraints: *OutputTray Inner *Stapling MR +*UIConstraints: *OutputTray Inner *Stapling LR +*UIConstraints: *OutputTray Inner *Stapling MT +*UIConstraints: *OutputTray Inner *Stapling MB +*UIConstraints: *OutputTray Inner *Stapling SS + +*UIConstraints: *OutputTray Inner *HolePunch LEP-0R +*UIConstraints: *OutputTray Inner *HolePunch SEP-0R +*UIConstraints: *OutputTray Inner *HolePunch LEP-180R +*UIConstraints: *OutputTray Inner *HolePunch SEP-180R + +*UIConstraints: *OutputTray Bin1 *Stapling ML +*UIConstraints: *OutputTray Bin1 *Stapling LL +*UIConstraints: *OutputTray Bin1 *Stapling UR +*UIConstraints: *OutputTray Bin1 *Stapling MR +*UIConstraints: *OutputTray Bin1 *Stapling LR +*UIConstraints: *OutputTray Bin1 *Stapling MT +*UIConstraints: *OutputTray Bin1 *Stapling MB +*UIConstraints: *OutputTray Bin1 *Stapling SS + +*UIConstraints: *Finisher StapleM *OutputTray SideExitTray +*UIConstraints: *Finisher StapleMH *OutputTray SideExitTray + +*UIConstraints: *OutputTray InnerU *Stapling UL +*UIConstraints: *OutputTray InnerU *Stapling ML +*UIConstraints: *OutputTray InnerU *Stapling LL +*UIConstraints: *OutputTray InnerU *Stapling UR +*UIConstraints: *OutputTray InnerU *Stapling MR +*UIConstraints: *OutputTray InnerU *Stapling LR +*UIConstraints: *OutputTray InnerU *Stapling MT +*UIConstraints: *OutputTray InnerU *Stapling MB +*UIConstraints: *OutputTray InnerU *Stapling SS + +*UIConstraints: *OutputTray InnerU *HolePunch LEP-0R +*UIConstraints: *OutputTray InnerU *HolePunch SEP-0R +*UIConstraints: *OutputTray InnerU *HolePunch LEP-180R +*UIConstraints: *OutputTray InnerU *HolePunch SEP-180R + +*UIConstraints: *Finisher None *Folding True +*UIConstraints: *Finisher Staple1 *Folding True +*UIConstraints: *Finisher InnerFinisher1 *Folding True +*UIConstraints: *Finisher InnerFinisher2 *Folding True + +*% ===== Cassette Constraints ===== + +*UIConstraints: *Pedestal Drawer1 *InputSlot LowerCassette +*UIConstraints: *Pedestal Drawer1 *InputSlot PedestalUpperCassette +*UIConstraints: *Pedestal Drawer1 *InputSlot PedestalLowerCassette +*UIConstraints: *Pedestal Drawer1 *InputSlot LCF + +*UIConstraints: *Pedestal Drawer1L *InputSlot LowerCassette +*UIConstraints: *Pedestal Drawer1L *InputSlot PedestalUpperCassette +*UIConstraints: *Pedestal Drawer1L *InputSlot PedestalLowerCassette + +*UIConstraints: *Pedestal Drawer12 *InputSlot PedestalUpperCassette +*UIConstraints: *Pedestal Drawer12 *InputSlot PedestalLowerCassette +*UIConstraints: *Pedestal Drawer12 *InputSlot LCF + +*UIConstraints: *Pedestal Drawer12L *InputSlot PedestalUpperCassette +*UIConstraints: *Pedestal Drawer12L *InputSlot PedestalLowerCassette + +*UIConstraints: *Pedestal Drawer123 *InputSlot PedestalLowerCassette +*UIConstraints: *Pedestal Drawer123 *InputSlot LCF + +*UIConstraints: *Pedestal Drawer1234 *InputSlot LCF + +*UIConstraints: *ExternalLCF None *InputSlot ExternalLCF + +*% ===== Quality Constraints ===== + +*%*UIConstraints: *ColorType Mono *ImageType General +*UIConstraints: *ColorType Mono *ImageType Photo +*UIConstraints: *ColorType Mono *ImageType Presentation +*UIConstraints: *ColorType Mono *ImageType LineArt + +*UIConstraints: *ColorType Mono *PureBlackGray BlackAuto +*UIConstraints: *ColorType Mono *PureBlackGray BlackText +*UIConstraints: *ColorType Mono *PureBlackGray BlackTextGraphic +*UIConstraints: *ColorType Mono *PureBlackGray BlackTextGraphicImage +*UIConstraints: *ColorType Mono *PureBlackGray BlackGrayAuto +*UIConstraints: *ColorType Mono *PureBlackGray BlackGrayText +*UIConstraints: *ColorType Mono *PureBlackGray BlackGrayTextGraphic +*UIConstraints: *ColorType Mono *PureBlackGray BlackGrayTextGraphicImage + +*%===== Paper Size ========= + +*UIConstraints: *PageSize A3 *MediaType Envelope +*UIConstraints: *PageSize A4 *MediaType Envelope +*UIConstraints: *PageSize A5 *MediaType Envelope +*UIConstraints: *PageSize A6 *MediaType Envelope +*UIConstraints: *PageSize B4 *MediaType Envelope +*UIConstraints: *PageSize B5 *MediaType Envelope +*UIConstraints: *PageSize Ledger *MediaType Envelope +*UIConstraints: *PageSize Legal *MediaType Envelope +*UIConstraints: *PageSize Letter *MediaType Envelope +*UIConstraints: *PageSize Statement *MediaType Envelope +*UIConstraints: *PageSize Folio *MediaType Envelope +*UIConstraints: *PageSize Computer *MediaType Envelope +*UIConstraints: *PageSize LG13 *MediaType Envelope +*UIConstraints: *PageSize SQ85 *MediaType Envelope +*UIConstraints: *PageSize Ledger-Wide *MediaType Envelope +*UIConstraints: *PageSize 1319inch *MediaType Envelope +*UIConstraints: *PageSize A3-Wide *MediaType Envelope +*UIConstraints: *PageSize Postcard *MediaType Envelope +*UIConstraints: *PageSize DoublePostcardRotated *MediaType Envelope +*UIConstraints: *PageSize 8K *MediaType Envelope +*UIConstraints: *PageSize 16K *MediaType Envelope +*UIConstraints: *PageSize LG135 *MediaType Envelope +*UIConstraints: *PageSize IndexCard *MediaType Envelope +*UIConstraints: *PageSize Executive *MediaType Envelope + +*UIConstraints: *PageSize A3 *MediaType Envelopeback +*UIConstraints: *PageSize A4 *MediaType Envelopeback +*UIConstraints: *PageSize A5 *MediaType Envelopeback +*UIConstraints: *PageSize A6 *MediaType Envelopeback +*UIConstraints: *PageSize B4 *MediaType Envelopeback +*UIConstraints: *PageSize B5 *MediaType Envelopeback +*UIConstraints: *PageSize Ledger *MediaType Envelopeback +*UIConstraints: *PageSize Legal *MediaType Envelopeback +*UIConstraints: *PageSize Letter *MediaType Envelopeback +*UIConstraints: *PageSize Statement *MediaType Envelopeback +*UIConstraints: *PageSize Folio *MediaType Envelopeback +*UIConstraints: *PageSize Computer *MediaType Envelopeback +*UIConstraints: *PageSize LG13 *MediaType Envelopeback +*UIConstraints: *PageSize SQ85 *MediaType Envelopeback +*UIConstraints: *PageSize Ledger-Wide *MediaType Envelopeback +*UIConstraints: *PageSize 1319inch *MediaType Envelopeback +*UIConstraints: *PageSize A3-Wide *MediaType Envelopeback +*UIConstraints: *PageSize Postcard *MediaType Envelopeback +*UIConstraints: *PageSize DoublePostcardRotated *MediaType Envelopeback +*UIConstraints: *PageSize 8K *MediaType Envelopeback +*UIConstraints: *PageSize 16K *MediaType Envelopeback +*UIConstraints: *PageSize LG135 *MediaType Envelopeback +*UIConstraints: *PageSize IndexCard *MediaType Envelopeback +*UIConstraints: *PageSize Executive *MediaType Envelopeback + +*UIConstraints: *PageSize A3 *MediaType Envelope1 +*UIConstraints: *PageSize A4 *MediaType Envelope1 +*UIConstraints: *PageSize A5 *MediaType Envelope1 +*UIConstraints: *PageSize A6 *MediaType Envelope1 +*UIConstraints: *PageSize B4 *MediaType Envelope1 +*UIConstraints: *PageSize B5 *MediaType Envelope1 +*UIConstraints: *PageSize Ledger *MediaType Envelope1 +*UIConstraints: *PageSize Legal *MediaType Envelope1 +*UIConstraints: *PageSize Letter *MediaType Envelope1 +*UIConstraints: *PageSize Statement *MediaType Envelope1 +*UIConstraints: *PageSize Folio *MediaType Envelope1 +*UIConstraints: *PageSize Computer *MediaType Envelope1 +*UIConstraints: *PageSize LG13 *MediaType Envelope1 +*UIConstraints: *PageSize SQ85 *MediaType Envelope1 +*UIConstraints: *PageSize Ledger-Wide *MediaType Envelope1 +*UIConstraints: *PageSize 1319inch *MediaType Envelope1 +*UIConstraints: *PageSize A3-Wide *MediaType Envelope1 +*UIConstraints: *PageSize Postcard *MediaType Envelope1 +*UIConstraints: *PageSize DoublePostcardRotated *MediaType Envelope1 +*UIConstraints: *PageSize 8K *MediaType Envelope1 +*UIConstraints: *PageSize 16K *MediaType Envelope1 +*UIConstraints: *PageSize LG135 *MediaType Envelope1 +*UIConstraints: *PageSize IndexCard *MediaType Envelope1 +*UIConstraints: *PageSize Executive *MediaType Envelope1 + +*UIConstraints: *PageSize A3 *MediaType Envelope2 +*UIConstraints: *PageSize A4 *MediaType Envelope2 +*UIConstraints: *PageSize A5 *MediaType Envelope2 +*UIConstraints: *PageSize A6 *MediaType Envelope2 +*UIConstraints: *PageSize B4 *MediaType Envelope2 +*UIConstraints: *PageSize B5 *MediaType Envelope2 +*UIConstraints: *PageSize Ledger *MediaType Envelope2 +*UIConstraints: *PageSize Legal *MediaType Envelope2 +*UIConstraints: *PageSize Letter *MediaType Envelope2 +*UIConstraints: *PageSize Statement *MediaType Envelope2 +*UIConstraints: *PageSize Folio *MediaType Envelope2 +*UIConstraints: *PageSize Computer *MediaType Envelope2 +*UIConstraints: *PageSize LG13 *MediaType Envelope2 +*UIConstraints: *PageSize SQ85 *MediaType Envelope2 +*UIConstraints: *PageSize Ledger-Wide *MediaType Envelope2 +*UIConstraints: *PageSize 1319inch *MediaType Envelope2 +*UIConstraints: *PageSize A3-Wide *MediaType Envelope2 +*UIConstraints: *PageSize Postcard *MediaType Envelope2 +*UIConstraints: *PageSize DoublePostcardRotated *MediaType Envelope2 +*UIConstraints: *PageSize 8K *MediaType Envelope2 +*UIConstraints: *PageSize 16K *MediaType Envelope2 +*UIConstraints: *PageSize LG135 *MediaType Envelope2 +*UIConstraints: *PageSize IndexCard *MediaType Envelope2 +*UIConstraints: *PageSize Executive *MediaType Envelope2 + +*UIConstraints: *PageSize A3 *MediaType Envelope3 +*UIConstraints: *PageSize A4 *MediaType Envelope3 +*UIConstraints: *PageSize A5 *MediaType Envelope3 +*UIConstraints: *PageSize A6 *MediaType Envelope3 +*UIConstraints: *PageSize B4 *MediaType Envelope3 +*UIConstraints: *PageSize B5 *MediaType Envelope3 +*UIConstraints: *PageSize Ledger *MediaType Envelope3 +*UIConstraints: *PageSize Legal *MediaType Envelope3 +*UIConstraints: *PageSize Letter *MediaType Envelope3 +*UIConstraints: *PageSize Statement *MediaType Envelope3 +*UIConstraints: *PageSize Folio *MediaType Envelope3 +*UIConstraints: *PageSize Computer *MediaType Envelope3 +*UIConstraints: *PageSize LG13 *MediaType Envelope3 +*UIConstraints: *PageSize SQ85 *MediaType Envelope3 +*UIConstraints: *PageSize Ledger-Wide *MediaType Envelope3 +*UIConstraints: *PageSize 1319inch *MediaType Envelope3 +*UIConstraints: *PageSize A3-Wide *MediaType Envelope3 +*UIConstraints: *PageSize Postcard *MediaType Envelope3 +*UIConstraints: *PageSize DoublePostcardRotated *MediaType Envelope3 +*UIConstraints: *PageSize 8K *MediaType Envelope3 +*UIConstraints: *PageSize 16K *MediaType Envelope3 +*UIConstraints: *PageSize LG135 *MediaType Envelope3 +*UIConstraints: *PageSize IndexCard *MediaType Envelope3 +*UIConstraints: *PageSize Executive *MediaType Envelope3 + +*UIConstraints: *PageSize A3 *MediaType Envelope4 +*UIConstraints: *PageSize A4 *MediaType Envelope4 +*UIConstraints: *PageSize A5 *MediaType Envelope4 +*UIConstraints: *PageSize A6 *MediaType Envelope4 +*UIConstraints: *PageSize B4 *MediaType Envelope4 +*UIConstraints: *PageSize B5 *MediaType Envelope4 +*UIConstraints: *PageSize Ledger *MediaType Envelope4 +*UIConstraints: *PageSize Legal *MediaType Envelope4 +*UIConstraints: *PageSize Letter *MediaType Envelope4 +*UIConstraints: *PageSize Statement *MediaType Envelope4 +*UIConstraints: *PageSize Folio *MediaType Envelope4 +*UIConstraints: *PageSize Computer *MediaType Envelope4 +*UIConstraints: *PageSize LG13 *MediaType Envelope4 +*UIConstraints: *PageSize SQ85 *MediaType Envelope4 +*UIConstraints: *PageSize Ledger-Wide *MediaType Envelope4 +*UIConstraints: *PageSize 1319inch *MediaType Envelope4 +*UIConstraints: *PageSize A3-Wide *MediaType Envelope4 +*UIConstraints: *PageSize Postcard *MediaType Envelope4 +*UIConstraints: *PageSize DoublePostcardRotated *MediaType Envelope4 +*UIConstraints: *PageSize 8K *MediaType Envelope4 +*UIConstraints: *PageSize 16K *MediaType Envelope4 +*UIConstraints: *PageSize LG135 *MediaType Envelope4 +*UIConstraints: *PageSize IndexCard *MediaType Envelope4 +*UIConstraints: *PageSize Executive *MediaType Envelope4 + +*UIConstraints: *PageSize Env9 *MediaType None +*UIConstraints: *PageSize Env9 *MediaType Plain +*UIConstraints: *PageSize Env9 *MediaType Plainback +*UIConstraints: *PageSize Env9 *MediaType PlainA +*UIConstraints: *PageSize Env9 *MediaType Plainthin +*UIConstraints: *PageSize Env9 *MediaType Plain1 +*UIConstraints: *PageSize Env9 *MediaType Plain2 +*UIConstraints: *PageSize Env9 *MediaType Thick1 +*UIConstraints: *PageSize Env9 *MediaType Thick1back +*UIConstraints: *PageSize Env9 *MediaType Thick2 +*UIConstraints: *PageSize Env9 *MediaType Thick2back +*UIConstraints: *PageSize Env9 *MediaType Thick3 +*UIConstraints: *PageSize Env9 *MediaType Thick3back +*UIConstraints: *PageSize Env9 *MediaType Thick4 +*UIConstraints: *PageSize Env9 *MediaType Thick4back +*UIConstraints: *PageSize Env9 *MediaType Thick5 +*UIConstraints: *PageSize Env9 *MediaType Transparency +*UIConstraints: *PageSize Env9 *MediaType Recycled +*UIConstraints: *PageSize Env9 *MediaType Recycledback +*UIConstraints: *PageSize Env9 *MediaType Special1 +*UIConstraints: *PageSize Env9 *MediaType Special1back +*UIConstraints: *PageSize Env9 *MediaType Special2 +*UIConstraints: *PageSize Env9 *MediaType Special2back +*UIConstraints: *PageSize Env9 *MediaType Special3 +*UIConstraints: *PageSize Env9 *MediaType Special3back +*UIConstraints: *PageSize Env9 *MediaType Special4 +*UIConstraints: *PageSize Env9 *MediaType Special5 +*UIConstraints: *PageSize Env9 *MediaType Special6 +*UIConstraints: *PageSize Env9 *MediaType Tab +*UIConstraints: *PageSize Env9 *MediaType Thin +*UIConstraints: *PageSize Env9 *MediaType Thinback +*UIConstraints: *PageSize Env9 *MediaType UserType1 +*UIConstraints: *PageSize Env9 *MediaType UserType2 +*UIConstraints: *PageSize Env9 *MediaType UserType3 +*UIConstraints: *PageSize Env9 *MediaType UserType4 +*UIConstraints: *PageSize Env9 *MediaType UserType5 + +*UIConstraints: *PageSize Env10 *MediaType None +*UIConstraints: *PageSize Env10 *MediaType Plain +*UIConstraints: *PageSize Env10 *MediaType Plainback +*UIConstraints: *PageSize Env10 *MediaType PlainA +*UIConstraints: *PageSize Env10 *MediaType Plainthin +*UIConstraints: *PageSize Env10 *MediaType Plain1 +*UIConstraints: *PageSize Env10 *MediaType Plain2 +*UIConstraints: *PageSize Env10 *MediaType Thick1 +*UIConstraints: *PageSize Env10 *MediaType Thick1back +*UIConstraints: *PageSize Env10 *MediaType Thick2 +*UIConstraints: *PageSize Env10 *MediaType Thick2back +*UIConstraints: *PageSize Env10 *MediaType Thick3 +*UIConstraints: *PageSize Env10 *MediaType Thick3back +*UIConstraints: *PageSize Env10 *MediaType Thick4 +*UIConstraints: *PageSize Env10 *MediaType Thick4back +*UIConstraints: *PageSize Env10 *MediaType Thick5 +*UIConstraints: *PageSize Env10 *MediaType Transparency +*UIConstraints: *PageSize Env10 *MediaType Recycled +*UIConstraints: *PageSize Env10 *MediaType Recycledback +*UIConstraints: *PageSize Env10 *MediaType Special1 +*UIConstraints: *PageSize Env10 *MediaType Special1back +*UIConstraints: *PageSize Env10 *MediaType Special2 +*UIConstraints: *PageSize Env10 *MediaType Special2back +*UIConstraints: *PageSize Env10 *MediaType Special3 +*UIConstraints: *PageSize Env10 *MediaType Special3back +*UIConstraints: *PageSize Env10 *MediaType Special4 +*UIConstraints: *PageSize Env10 *MediaType Special5 +*UIConstraints: *PageSize Env10 *MediaType Special6 +*UIConstraints: *PageSize Env10 *MediaType Tab +*UIConstraints: *PageSize Env10 *MediaType Thin +*UIConstraints: *PageSize Env10 *MediaType Thinback +*UIConstraints: *PageSize Env10 *MediaType UserType1 +*UIConstraints: *PageSize Env10 *MediaType UserType2 +*UIConstraints: *PageSize Env10 *MediaType UserType3 +*UIConstraints: *PageSize Env10 *MediaType UserType4 +*UIConstraints: *PageSize Env10 *MediaType UserType5 + +*UIConstraints: *PageSize EnvMonarch *MediaType None +*UIConstraints: *PageSize EnvMonarch *MediaType Plain +*UIConstraints: *PageSize EnvMonarch *MediaType Plainback +*UIConstraints: *PageSize EnvMonarch *MediaType PlainA +*UIConstraints: *PageSize EnvMonarch *MediaType Plainthin +*UIConstraints: *PageSize EnvMonarch *MediaType Plain1 +*UIConstraints: *PageSize EnvMonarch *MediaType Plain2 +*UIConstraints: *PageSize EnvMonarch *MediaType Thick1 +*UIConstraints: *PageSize EnvMonarch *MediaType Thick1back +*UIConstraints: *PageSize EnvMonarch *MediaType Thick2 +*UIConstraints: *PageSize EnvMonarch *MediaType Thick2back +*UIConstraints: *PageSize EnvMonarch *MediaType Thick3 +*UIConstraints: *PageSize EnvMonarch *MediaType Thick3back +*UIConstraints: *PageSize EnvMonarch *MediaType Thick4 +*UIConstraints: *PageSize EnvMonarch *MediaType Thick4back +*UIConstraints: *PageSize EnvMonarch *MediaType Thick5 +*UIConstraints: *PageSize EnvMonarch *MediaType Transparency +*UIConstraints: *PageSize EnvMonarch *MediaType Recycled +*UIConstraints: *PageSize EnvMonarch *MediaType Recycledback +*UIConstraints: *PageSize EnvMonarch *MediaType Special1 +*UIConstraints: *PageSize EnvMonarch *MediaType Special1back +*UIConstraints: *PageSize EnvMonarch *MediaType Special2 +*UIConstraints: *PageSize EnvMonarch *MediaType Special2back +*UIConstraints: *PageSize EnvMonarch *MediaType Special3 +*UIConstraints: *PageSize EnvMonarch *MediaType Special3back +*UIConstraints: *PageSize EnvMonarch *MediaType Special4 +*UIConstraints: *PageSize EnvMonarch *MediaType Special5 +*UIConstraints: *PageSize EnvMonarch *MediaType Special6 +*UIConstraints: *PageSize EnvMonarch *MediaType Tab +*UIConstraints: *PageSize EnvMonarch *MediaType Thin +*UIConstraints: *PageSize EnvMonarch *MediaType Thinback +*UIConstraints: *PageSize EnvMonarch *MediaType UserType1 +*UIConstraints: *PageSize EnvMonarch *MediaType UserType2 +*UIConstraints: *PageSize EnvMonarch *MediaType UserType3 +*UIConstraints: *PageSize EnvMonarch *MediaType UserType4 +*UIConstraints: *PageSize EnvMonarch *MediaType UserType5 + +*UIConstraints: *PageSize EnvPRC5 *MediaType None +*UIConstraints: *PageSize EnvPRC5 *MediaType Plain +*UIConstraints: *PageSize EnvPRC5 *MediaType Plainback +*UIConstraints: *PageSize EnvPRC5 *MediaType PlainA +*UIConstraints: *PageSize EnvPRC5 *MediaType Plainthin +*UIConstraints: *PageSize EnvPRC5 *MediaType Plain1 +*UIConstraints: *PageSize EnvPRC5 *MediaType Plain2 +*UIConstraints: *PageSize EnvPRC5 *MediaType Thick1 +*UIConstraints: *PageSize EnvPRC5 *MediaType Thick1back +*UIConstraints: *PageSize EnvPRC5 *MediaType Thick2 +*UIConstraints: *PageSize EnvPRC5 *MediaType Thick2back +*UIConstraints: *PageSize EnvPRC5 *MediaType Thick3 +*UIConstraints: *PageSize EnvPRC5 *MediaType Thick3back +*UIConstraints: *PageSize EnvPRC5 *MediaType Thick4 +*UIConstraints: *PageSize EnvPRC5 *MediaType Thick4back +*UIConstraints: *PageSize EnvPRC5 *MediaType Thick5 +*UIConstraints: *PageSize EnvPRC5 *MediaType Transparency +*UIConstraints: *PageSize EnvPRC5 *MediaType Recycled +*UIConstraints: *PageSize EnvPRC5 *MediaType Recycledback +*UIConstraints: *PageSize EnvPRC5 *MediaType Special1 +*UIConstraints: *PageSize EnvPRC5 *MediaType Special1back +*UIConstraints: *PageSize EnvPRC5 *MediaType Special2 +*UIConstraints: *PageSize EnvPRC5 *MediaType Special2back +*UIConstraints: *PageSize EnvPRC5 *MediaType Special3 +*UIConstraints: *PageSize EnvPRC5 *MediaType Special3back +*UIConstraints: *PageSize EnvPRC5 *MediaType Special4 +*UIConstraints: *PageSize EnvPRC5 *MediaType Special5 +*UIConstraints: *PageSize EnvPRC5 *MediaType Special6 +*UIConstraints: *PageSize EnvPRC5 *MediaType Tab +*UIConstraints: *PageSize EnvPRC5 *MediaType Thin +*UIConstraints: *PageSize EnvPRC5 *MediaType Thinback +*UIConstraints: *PageSize EnvPRC5 *MediaType UserType1 +*UIConstraints: *PageSize EnvPRC5 *MediaType UserType2 +*UIConstraints: *PageSize EnvPRC5 *MediaType UserType3 +*UIConstraints: *PageSize EnvPRC5 *MediaType UserType4 +*UIConstraints: *PageSize EnvPRC5 *MediaType UserType5 + +*UIConstraints: *PageSize EnvChou3 *MediaType None +*UIConstraints: *PageSize EnvChou3 *MediaType Plain +*UIConstraints: *PageSize EnvChou3 *MediaType Plainback +*UIConstraints: *PageSize EnvChou3 *MediaType PlainA +*UIConstraints: *PageSize EnvChou3 *MediaType Plainthin +*UIConstraints: *PageSize EnvChou3 *MediaType Plain1 +*UIConstraints: *PageSize EnvChou3 *MediaType Plain2 +*UIConstraints: *PageSize EnvChou3 *MediaType Thick1 +*UIConstraints: *PageSize EnvChou3 *MediaType Thick1back +*UIConstraints: *PageSize EnvChou3 *MediaType Thick2 +*UIConstraints: *PageSize EnvChou3 *MediaType Thick2back +*UIConstraints: *PageSize EnvChou3 *MediaType Thick3 +*UIConstraints: *PageSize EnvChou3 *MediaType Thick3back +*UIConstraints: *PageSize EnvChou3 *MediaType Thick4 +*UIConstraints: *PageSize EnvChou3 *MediaType Thick4back +*UIConstraints: *PageSize EnvChou3 *MediaType Thick5 +*UIConstraints: *PageSize EnvChou3 *MediaType Transparency +*UIConstraints: *PageSize EnvChou3 *MediaType Recycled +*UIConstraints: *PageSize EnvChou3 *MediaType Recycledback +*UIConstraints: *PageSize EnvChou3 *MediaType Special1 +*UIConstraints: *PageSize EnvChou3 *MediaType Special1back +*UIConstraints: *PageSize EnvChou3 *MediaType Special2 +*UIConstraints: *PageSize EnvChou3 *MediaType Special2back +*UIConstraints: *PageSize EnvChou3 *MediaType Special3 +*UIConstraints: *PageSize EnvChou3 *MediaType Special3back +*UIConstraints: *PageSize EnvChou3 *MediaType Special4 +*UIConstraints: *PageSize EnvChou3 *MediaType Special5 +*UIConstraints: *PageSize EnvChou3 *MediaType Special6 +*UIConstraints: *PageSize EnvChou3 *MediaType Tab +*UIConstraints: *PageSize EnvChou3 *MediaType Thin +*UIConstraints: *PageSize EnvChou3 *MediaType Thinback +*UIConstraints: *PageSize EnvChou3 *MediaType UserType1 +*UIConstraints: *PageSize EnvChou3 *MediaType UserType2 +*UIConstraints: *PageSize EnvChou3 *MediaType UserType3 +*UIConstraints: *PageSize EnvChou3 *MediaType UserType4 +*UIConstraints: *PageSize EnvChou3 *MediaType UserType5 + +*UIConstraints: *PageSize EnvChou4 *MediaType None +*UIConstraints: *PageSize EnvChou4 *MediaType Plain +*UIConstraints: *PageSize EnvChou4 *MediaType Plainback +*UIConstraints: *PageSize EnvChou4 *MediaType PlainA +*UIConstraints: *PageSize EnvChou4 *MediaType Plainthin +*UIConstraints: *PageSize EnvChou4 *MediaType Plain1 +*UIConstraints: *PageSize EnvChou4 *MediaType Plain2 +*UIConstraints: *PageSize EnvChou4 *MediaType Thick1 +*UIConstraints: *PageSize EnvChou4 *MediaType Thick1back +*UIConstraints: *PageSize EnvChou4 *MediaType Thick2 +*UIConstraints: *PageSize EnvChou4 *MediaType Thick2back +*UIConstraints: *PageSize EnvChou4 *MediaType Thick3 +*UIConstraints: *PageSize EnvChou4 *MediaType Thick3back +*UIConstraints: *PageSize EnvChou4 *MediaType Thick4 +*UIConstraints: *PageSize EnvChou4 *MediaType Thick4back +*UIConstraints: *PageSize EnvChou4 *MediaType Thick5 +*UIConstraints: *PageSize EnvChou4 *MediaType Transparency +*UIConstraints: *PageSize EnvChou4 *MediaType Recycled +*UIConstraints: *PageSize EnvChou4 *MediaType Recycledback +*UIConstraints: *PageSize EnvChou4 *MediaType Special1 +*UIConstraints: *PageSize EnvChou4 *MediaType Special1back +*UIConstraints: *PageSize EnvChou4 *MediaType Special2 +*UIConstraints: *PageSize EnvChou4 *MediaType Special2back +*UIConstraints: *PageSize EnvChou4 *MediaType Special3 +*UIConstraints: *PageSize EnvChou4 *MediaType Special3back +*UIConstraints: *PageSize EnvChou4 *MediaType Special4 +*UIConstraints: *PageSize EnvChou4 *MediaType Special5 +*UIConstraints: *PageSize EnvChou4 *MediaType Special6 +*UIConstraints: *PageSize EnvChou4 *MediaType Tab +*UIConstraints: *PageSize EnvChou4 *MediaType Thin +*UIConstraints: *PageSize EnvChou4 *MediaType Thinback +*UIConstraints: *PageSize EnvChou4 *MediaType UserType1 +*UIConstraints: *PageSize EnvChou4 *MediaType UserType2 +*UIConstraints: *PageSize EnvChou4 *MediaType UserType3 +*UIConstraints: *PageSize EnvChou4 *MediaType UserType4 +*UIConstraints: *PageSize EnvChou4 *MediaType UserType5 + +*UIConstraints: *PageSize EnvYou4 *MediaType None +*UIConstraints: *PageSize EnvYou4 *MediaType Plain +*UIConstraints: *PageSize EnvYou4 *MediaType Plainback +*UIConstraints: *PageSize EnvYou4 *MediaType PlainA +*UIConstraints: *PageSize EnvYou4 *MediaType Plainthin +*UIConstraints: *PageSize EnvYou4 *MediaType Plain1 +*UIConstraints: *PageSize EnvYou4 *MediaType Plain2 +*UIConstraints: *PageSize EnvYou4 *MediaType Thick1 +*UIConstraints: *PageSize EnvYou4 *MediaType Thick1back +*UIConstraints: *PageSize EnvYou4 *MediaType Thick2 +*UIConstraints: *PageSize EnvYou4 *MediaType Thick2back +*UIConstraints: *PageSize EnvYou4 *MediaType Thick3 +*UIConstraints: *PageSize EnvYou4 *MediaType Thick3back +*UIConstraints: *PageSize EnvYou4 *MediaType Thick4 +*UIConstraints: *PageSize EnvYou4 *MediaType Thick4back +*UIConstraints: *PageSize EnvYou4 *MediaType Thick5 +*UIConstraints: *PageSize EnvYou4 *MediaType Transparency +*UIConstraints: *PageSize EnvYou4 *MediaType Recycled +*UIConstraints: *PageSize EnvYou4 *MediaType Recycledback +*UIConstraints: *PageSize EnvYou4 *MediaType Special1 +*UIConstraints: *PageSize EnvYou4 *MediaType Special1back +*UIConstraints: *PageSize EnvYou4 *MediaType Special2 +*UIConstraints: *PageSize EnvYou4 *MediaType Special2back +*UIConstraints: *PageSize EnvYou4 *MediaType Special3 +*UIConstraints: *PageSize EnvYou4 *MediaType Special3back +*UIConstraints: *PageSize EnvYou4 *MediaType Special4 +*UIConstraints: *PageSize EnvYou4 *MediaType Special5 +*UIConstraints: *PageSize EnvYou4 *MediaType Special6 +*UIConstraints: *PageSize EnvYou4 *MediaType Tab +*UIConstraints: *PageSize EnvYou4 *MediaType Thin +*UIConstraints: *PageSize EnvYou4 *MediaType Thinback +*UIConstraints: *PageSize EnvYou4 *MediaType UserType1 +*UIConstraints: *PageSize EnvYou4 *MediaType UserType2 +*UIConstraints: *PageSize EnvYou4 *MediaType UserType3 +*UIConstraints: *PageSize EnvYou4 *MediaType UserType4 +*UIConstraints: *PageSize EnvYou4 *MediaType UserType5 + +*UIConstraints: *PageSize EnvC5 *MediaType None +*UIConstraints: *PageSize EnvC5 *MediaType Plain +*UIConstraints: *PageSize EnvC5 *MediaType Plainback +*UIConstraints: *PageSize EnvC5 *MediaType PlainA +*UIConstraints: *PageSize EnvC5 *MediaType Plainthin +*UIConstraints: *PageSize EnvC5 *MediaType Plain1 +*UIConstraints: *PageSize EnvC5 *MediaType Plain2 +*UIConstraints: *PageSize EnvC5 *MediaType Thick1 +*UIConstraints: *PageSize EnvC5 *MediaType Thick1back +*UIConstraints: *PageSize EnvC5 *MediaType Thick2 +*UIConstraints: *PageSize EnvC5 *MediaType Thick2back +*UIConstraints: *PageSize EnvC5 *MediaType Thick3 +*UIConstraints: *PageSize EnvC5 *MediaType Thick3back +*UIConstraints: *PageSize EnvC5 *MediaType Thick4 +*UIConstraints: *PageSize EnvC5 *MediaType Thick4back +*UIConstraints: *PageSize EnvC5 *MediaType Thick5 +*UIConstraints: *PageSize EnvC5 *MediaType Transparency +*UIConstraints: *PageSize EnvC5 *MediaType Recycled +*UIConstraints: *PageSize EnvC5 *MediaType Recycledback +*UIConstraints: *PageSize EnvC5 *MediaType Special1 +*UIConstraints: *PageSize EnvC5 *MediaType Special1back +*UIConstraints: *PageSize EnvC5 *MediaType Special2 +*UIConstraints: *PageSize EnvC5 *MediaType Special2back +*UIConstraints: *PageSize EnvC5 *MediaType Special3 +*UIConstraints: *PageSize EnvC5 *MediaType Special3back +*UIConstraints: *PageSize EnvC5 *MediaType Special4 +*UIConstraints: *PageSize EnvC5 *MediaType Special5 +*UIConstraints: *PageSize EnvC5 *MediaType Special6 +*UIConstraints: *PageSize EnvC5 *MediaType Tab +*UIConstraints: *PageSize EnvC5 *MediaType Thin +*UIConstraints: *PageSize EnvC5 *MediaType Thinback +*UIConstraints: *PageSize EnvC5 *MediaType UserType1 +*UIConstraints: *PageSize EnvC5 *MediaType UserType2 +*UIConstraints: *PageSize EnvC5 *MediaType UserType3 +*UIConstraints: *PageSize EnvC5 *MediaType UserType4 +*UIConstraints: *PageSize EnvC5 *MediaType UserType5 + +*UIConstraints: *PageSize A6 *InputSlot UpperCassette +*UIConstraints: *PageSize A6 *InputSlot LowerCassette +*UIConstraints: *PageSize A6 *InputSlot LCF +*UIConstraints: *PageSize A6 *InputSlot ExternalLCF +*UIConstraints: *PageSize A6 *InputSlot PedestalUpperCassette +*UIConstraints: *PageSize A6 *InputSlot PedestalLowerCassette +*UIConstraints: *PageSize A6 *MediaType Transparency + +*UIConstraints: *PageSize 320450mm *InputSlot UpperCassette +*UIConstraints: *PageSize 320450mm *InputSlot LowerCassette +*UIConstraints: *PageSize 320450mm *InputSlot LCF +*UIConstraints: *PageSize 320450mm *InputSlot ExternalLCF +*UIConstraints: *PageSize 320450mm *InputSlot PedestalUpperCassette +*UIConstraints: *PageSize 320450mm *InputSlot PedestalLowerCassette + +*UIConstraints: *PageSize 320460mm *InputSlot UpperCassette +*UIConstraints: *PageSize 320460mm *InputSlot LowerCassette +*UIConstraints: *PageSize 320460mm *InputSlot LCF +*UIConstraints: *PageSize 320460mm *InputSlot ExternalLCF +*UIConstraints: *PageSize 320460mm *InputSlot PedestalUpperCassette +*UIConstraints: *PageSize 320460mm *InputSlot PedestalLowerCassette + +*UIConstraints: *PageSize Ledger-Wide *InputSlot UpperCassette +*UIConstraints: *PageSize Ledger-Wide *InputSlot LowerCassette +*UIConstraints: *PageSize Ledger-Wide *InputSlot LCF +*UIConstraints: *PageSize Ledger-Wide *InputSlot ExternalLCF +*UIConstraints: *PageSize Ledger-Wide *InputSlot PedestalUpperCassette +*UIConstraints: *PageSize Ledger-Wide *InputSlot PedestalLowerCassette +*UIConstraints: *PageSize Ledger-Wide *MediaType Transparency + +*UIConstraints: *PageSize A3-Wide *InputSlot UpperCassette +*UIConstraints: *PageSize A3-Wide *InputSlot LowerCassette +*UIConstraints: *PageSize A3-Wide *InputSlot LCF +*UIConstraints: *PageSize A3-Wide *InputSlot ExternalLCF +*UIConstraints: *PageSize A3-Wide *InputSlot PedestalUpperCassette +*UIConstraints: *PageSize A3-Wide *InputSlot PedestalLowerCassette +*UIConstraints: *PageSize A3-Wide *MediaType Transparency + +*UIConstraints: *PageSize Statement *InputSlot UpperCassette +*UIConstraints: *PageSize Statement *InputSlot LowerCassette +*UIConstraints: *PageSize Statement *InputSlot LCF +*UIConstraints: *PageSize Statement *InputSlot PedestalUpperCassette +*UIConstraints: *PageSize Statement *InputSlot PedestalLowerCassette + +*UIConstraints: *InputSlot LCF *PageSize A3 +*UIConstraints: *InputSlot LCF *PageSize A5 +*UIConstraints: *InputSlot LCF *PageSize A6 +*UIConstraints: *InputSlot LCF *PageSize B4 +*UIConstraints: *InputSlot LCF *PageSize B5 +*UIConstraints: *InputSlot LCF *PageSize Ledger +*UIConstraints: *InputSlot LCF *PageSize Statement +*UIConstraints: *InputSlot LCF *PageSize Folio +*UIConstraints: *InputSlot LCF *PageSize Computer +*UIConstraints: *InputSlot LCF *PageSize SQ85 +*UIConstraints: *InputSlot LCF *PageSize Ledger-Wide +*UIConstraints: *InputSlot LCF *PageSize 1319inch +*UIConstraints: *InputSlot LCF *PageSize A3-Wide +*UIConstraints: *InputSlot LCF *PageSize Postcard +*UIConstraints: *InputSlot LCF *PageSize DoublePostcardRotated +*UIConstraints: *InputSlot LCF *PageSize 8K +*UIConstraints: *InputSlot LCF *PageSize 16K +*UIConstraints: *InputSlot LCF *PageSize Env9 +*UIConstraints: *InputSlot LCF *PageSize Env10 +*UIConstraints: *InputSlot LCF *PageSize EnvMonarch +*UIConstraints: *InputSlot LCF *PageSize EnvPRC5 +*UIConstraints: *InputSlot LCF *PageSize EnvChou3 +*UIConstraints: *InputSlot LCF *PageSize EnvChou4 +*UIConstraints: *InputSlot LCF *PageSize EnvYou4 +*UIConstraints: *InputSlot LCF *PageSize EnvC5 +*UIConstraints: *InputSlot LCF *PageSize 320450mm +*UIConstraints: *InputSlot LCF *PageSize 320460mm +*UIConstraints: *InputSlot LCF *PageSize IndexCard +*UIConstraints: *InputSlot LCF *PageSize Executive + +*UIConstraints: *InputSlot ExternalLCF *PageSize A3 +*UIConstraints: *InputSlot ExternalLCF *PageSize A5 +*UIConstraints: *InputSlot ExternalLCF *PageSize A6 +*UIConstraints: *InputSlot ExternalLCF *PageSize B4 +*UIConstraints: *InputSlot ExternalLCF *PageSize B5 +*UIConstraints: *InputSlot ExternalLCF *PageSize Ledger +*UIConstraints: *InputSlot ExternalLCF *PageSize Statement +*UIConstraints: *InputSlot ExternalLCF *PageSize Folio +*UIConstraints: *InputSlot ExternalLCF *PageSize Computer +*UIConstraints: *InputSlot ExternalLCF *PageSize SQ85 +*UIConstraints: *InputSlot ExternalLCF *PageSize Ledger-Wide +*UIConstraints: *InputSlot ExternalLCF *PageSize 1319inch +*UIConstraints: *InputSlot ExternalLCF *PageSize A3-Wide +*UIConstraints: *InputSlot ExternalLCF *PageSize Postcard +*UIConstraints: *InputSlot ExternalLCF *PageSize DoublePostcardRotated +*UIConstraints: *InputSlot ExternalLCF *PageSize 8K +*UIConstraints: *InputSlot ExternalLCF *PageSize 16K +*UIConstraints: *InputSlot ExternalLCF *PageSize Env9 +*UIConstraints: *InputSlot ExternalLCF *PageSize Env10 +*UIConstraints: *InputSlot ExternalLCF *PageSize EnvMonarch +*UIConstraints: *InputSlot ExternalLCF *PageSize EnvPRC5 +*UIConstraints: *InputSlot ExternalLCF *PageSize EnvChou3 +*UIConstraints: *InputSlot ExternalLCF *PageSize EnvChou4 +*UIConstraints: *InputSlot ExternalLCF *PageSize EnvYou4 +*UIConstraints: *InputSlot ExternalLCF *PageSize EnvC5 +*UIConstraints: *InputSlot ExternalLCF *PageSize 320450mm +*UIConstraints: *InputSlot ExternalLCF *PageSize 320460mm +*UIConstraints: *InputSlot ExternalLCF *PageSize IndexCard +*UIConstraints: *InputSlot ExternalLCF *PageSize Executive + +*%===== Media Type ========= + +*UIConstraints: *MediaType Special1 *OutputTray Bin2 +*UIConstraints: *MediaType Special1back *OutputTray Bin2 +*UIConstraints: *MediaType Special2 *OutputTray Bin2 +*UIConstraints: *MediaType Special2back *OutputTray Bin2 +*UIConstraints: *MediaType Thick4 *OutputTray Bin1 +*UIConstraints: *MediaType Thick4back *OutputTray Bin1 +*UIConstraints: *MediaType Thick4 *OutputTray Bin2 +*UIConstraints: *MediaType Thick4back *OutputTray Bin2 +*UIConstraints: *MediaType Thick5 *OutputTray Bin1 +*UIConstraints: *MediaType Transparency *OutputTray Bin1 + +*%===== Custom Paper Size ========= + +*%*NonUIConstraints: *CustomPageSize True *InputSlot UpperCassette +*%*NonUIConstraints: *CustomPageSize True *InputSlot LCF +*%*NonUIConstraints: *CustomPageSize True *InputSlot PedestalUpperCassette +*%*NonUIConstraints: *CustomPageSize True *InputSlot LowerCassette +*%*NonUIConstraints: *CustomPageSize True *InputSlot PedestalLowerCassette +*%*NonUIConstraints: *CustomPageSize True *InputSlot ExternalLCF + +*%*NonUIConstraints: *InputSlot UpperCassette *CustomPageSize True +*%*NonUIConstraints: *InputSlot LowerCassette *CustomPageSize True +*%*NonUIConstraints: *InputSlot LCF *CustomPageSize True +*%*NonUIConstraints: *InputSlot PedestalUpperCassette *CustomPageSize True +*%*NonUIConstraints: *InputSlot PedestalLowerCassette *CustomPageSize True +*%*NonUIConstraints: *InputSlot ExternalLCF *CustomPageSize True + +*%===== Print Mode ================ +*UIConstraints: *PrintMode Hold *HardDisk False +*UIConstraints: *PrintMode Proof *HardDisk False +*UIConstraints: *PrintMode Private *HardDisk False + +*%=== Color Setting ============== +*UIConstraints: *ColorType Mono *PostScriptOverprint True +*UIConstraints: *ColorType Black&Red *PostScriptOverprint True +*UIConstraints: *ColorType Black&Green *PostScriptOverprint True +*UIConstraints: *ColorType Black&Blue *PostScriptOverprint True +*UIConstraints: *ColorType Black&Cyan *PostScriptOverprint True +*UIConstraints: *ColorType Black&Magenta *PostScriptOverprint True +*UIConstraints: *ColorType Black&Yellow *PostScriptOverprint True +*UIConstraints: *ColorType Black&White *PostScriptOverprint True + +*UIConstraints: *ColorType Mono *ColorBalanceCyan -1 +*UIConstraints: *ColorType Mono *ColorBalanceCyan -2 +*UIConstraints: *ColorType Mono *ColorBalanceCyan -3 +*UIConstraints: *ColorType Mono *ColorBalanceCyan -4 +*UIConstraints: *ColorType Mono *ColorBalanceCyan 1 +*UIConstraints: *ColorType Mono *ColorBalanceCyan 2 +*UIConstraints: *ColorType Mono *ColorBalanceCyan 3 +*UIConstraints: *ColorType Mono *ColorBalanceCyan 4 + +*UIConstraints: *ColorType Mono *ColorBalanceMagenta -1 +*UIConstraints: *ColorType Mono *ColorBalanceMagenta -2 +*UIConstraints: *ColorType Mono *ColorBalanceMagenta -3 +*UIConstraints: *ColorType Mono *ColorBalanceMagenta -4 +*UIConstraints: *ColorType Mono *ColorBalanceMagenta 1 +*UIConstraints: *ColorType Mono *ColorBalanceMagenta 2 +*UIConstraints: *ColorType Mono *ColorBalanceMagenta 3 +*UIConstraints: *ColorType Mono *ColorBalanceMagenta 4 + +*UIConstraints: *ColorType Mono *ColorBalanceYellow -1 +*UIConstraints: *ColorType Mono *ColorBalanceYellow -2 +*UIConstraints: *ColorType Mono *ColorBalanceYellow -3 +*UIConstraints: *ColorType Mono *ColorBalanceYellow -4 +*UIConstraints: *ColorType Mono *ColorBalanceYellow 1 +*UIConstraints: *ColorType Mono *ColorBalanceYellow 2 +*UIConstraints: *ColorType Mono *ColorBalanceYellow 3 +*UIConstraints: *ColorType Mono *ColorBalanceYellow 4 + +*UIConstraints: *ColorType Black&Red *PureBlackGray BlackAuto +*UIConstraints: *ColorType Black&Red *PureBlackGray BlackText +*UIConstraints: *ColorType Black&Red *PureBlackGray BlackTextGraphic +*UIConstraints: *ColorType Black&Red *PureBlackGray BlackTextGraphicImage +*UIConstraints: *ColorType Black&Red *PureBlackGray BlackGrayAuto +*UIConstraints: *ColorType Black&Red *PureBlackGray BlackGrayText +*UIConstraints: *ColorType Black&Red *PureBlackGray BlackGrayTextGraphic +*UIConstraints: *ColorType Black&Red *PureBlackGray BlackGrayTextGraphicImage + +*UIConstraints: *ColorType Black&Red *ColorBalanceCyan -1 +*UIConstraints: *ColorType Black&Red *ColorBalanceCyan -2 +*UIConstraints: *ColorType Black&Red *ColorBalanceCyan -3 +*UIConstraints: *ColorType Black&Red *ColorBalanceCyan -4 +*UIConstraints: *ColorType Black&Red *ColorBalanceCyan 1 +*UIConstraints: *ColorType Black&Red *ColorBalanceCyan 2 +*UIConstraints: *ColorType Black&Red *ColorBalanceCyan 3 +*UIConstraints: *ColorType Black&Red *ColorBalanceCyan 4 + +*UIConstraints: *ColorType Black&Red *ColorBalanceMagenta -1 +*UIConstraints: *ColorType Black&Red *ColorBalanceMagenta -2 +*UIConstraints: *ColorType Black&Red *ColorBalanceMagenta -3 +*UIConstraints: *ColorType Black&Red *ColorBalanceMagenta -4 +*UIConstraints: *ColorType Black&Red *ColorBalanceMagenta 1 +*UIConstraints: *ColorType Black&Red *ColorBalanceMagenta 2 +*UIConstraints: *ColorType Black&Red *ColorBalanceMagenta 3 +*UIConstraints: *ColorType Black&Red *ColorBalanceMagenta 4 + +*UIConstraints: *ColorType Black&Red *ColorBalanceYellow -1 +*UIConstraints: *ColorType Black&Red *ColorBalanceYellow -2 +*UIConstraints: *ColorType Black&Red *ColorBalanceYellow -3 +*UIConstraints: *ColorType Black&Red *ColorBalanceYellow -4 +*UIConstraints: *ColorType Black&Red *ColorBalanceYellow 1 +*UIConstraints: *ColorType Black&Red *ColorBalanceYellow 2 +*UIConstraints: *ColorType Black&Red *ColorBalanceYellow 3 +*UIConstraints: *ColorType Black&Red *ColorBalanceYellow 4 + +*UIConstraints: *ColorType Black&Green *PureBlackGray BlackAuto +*UIConstraints: *ColorType Black&Green *PureBlackGray BlackText +*UIConstraints: *ColorType Black&Green *PureBlackGray BlackTextGraphic +*UIConstraints: *ColorType Black&Green *PureBlackGray BlackTextGraphicImage +*UIConstraints: *ColorType Black&Green *PureBlackGray BlackGrayAuto +*UIConstraints: *ColorType Black&Green *PureBlackGray BlackGrayText +*UIConstraints: *ColorType Black&Green *PureBlackGray BlackGrayTextGraphic +*UIConstraints: *ColorType Black&Green *PureBlackGray BlackGrayTextGraphicImage + +*UIConstraints: *ColorType Black&Green *ColorBalanceCyan -1 +*UIConstraints: *ColorType Black&Green *ColorBalanceCyan -2 +*UIConstraints: *ColorType Black&Green *ColorBalanceCyan -3 +*UIConstraints: *ColorType Black&Green *ColorBalanceCyan -4 +*UIConstraints: *ColorType Black&Green *ColorBalanceCyan 1 +*UIConstraints: *ColorType Black&Green *ColorBalanceCyan 2 +*UIConstraints: *ColorType Black&Green *ColorBalanceCyan 3 +*UIConstraints: *ColorType Black&Green *ColorBalanceCyan 4 + +*UIConstraints: *ColorType Black&Green *ColorBalanceMagenta -1 +*UIConstraints: *ColorType Black&Green *ColorBalanceMagenta -2 +*UIConstraints: *ColorType Black&Green *ColorBalanceMagenta -3 +*UIConstraints: *ColorType Black&Green *ColorBalanceMagenta -4 +*UIConstraints: *ColorType Black&Green *ColorBalanceMagenta 1 +*UIConstraints: *ColorType Black&Green *ColorBalanceMagenta 2 +*UIConstraints: *ColorType Black&Green *ColorBalanceMagenta 3 +*UIConstraints: *ColorType Black&Green *ColorBalanceMagenta 4 + +*UIConstraints: *ColorType Black&Green *ColorBalanceYellow -1 +*UIConstraints: *ColorType Black&Green *ColorBalanceYellow -2 +*UIConstraints: *ColorType Black&Green *ColorBalanceYellow -3 +*UIConstraints: *ColorType Black&Green *ColorBalanceYellow -4 +*UIConstraints: *ColorType Black&Green *ColorBalanceYellow 1 +*UIConstraints: *ColorType Black&Green *ColorBalanceYellow 2 +*UIConstraints: *ColorType Black&Green *ColorBalanceYellow 3 +*UIConstraints: *ColorType Black&Green *ColorBalanceYellow 4 + +*UIConstraints: *ColorType Black&Blue *PureBlackGray BlackAuto +*UIConstraints: *ColorType Black&Blue *PureBlackGray BlackText +*UIConstraints: *ColorType Black&Blue *PureBlackGray BlackTextGraphic +*UIConstraints: *ColorType Black&Blue *PureBlackGray BlackTextGraphicImage +*UIConstraints: *ColorType Black&Blue *PureBlackGray BlackGrayAuto +*UIConstraints: *ColorType Black&Blue *PureBlackGray BlackGrayText +*UIConstraints: *ColorType Black&Blue *PureBlackGray BlackGrayTextGraphic +*UIConstraints: *ColorType Black&Blue *PureBlackGray BlackGrayTextGraphicImage + +*UIConstraints: *ColorType Black&Blue *ColorBalanceCyan -1 +*UIConstraints: *ColorType Black&Blue *ColorBalanceCyan -2 +*UIConstraints: *ColorType Black&Blue *ColorBalanceCyan -3 +*UIConstraints: *ColorType Black&Blue *ColorBalanceCyan -4 +*UIConstraints: *ColorType Black&Blue *ColorBalanceCyan 1 +*UIConstraints: *ColorType Black&Blue *ColorBalanceCyan 2 +*UIConstraints: *ColorType Black&Blue *ColorBalanceCyan 3 +*UIConstraints: *ColorType Black&Blue *ColorBalanceCyan 4 + +*UIConstraints: *ColorType Black&Blue *ColorBalanceMagenta -1 +*UIConstraints: *ColorType Black&Blue *ColorBalanceMagenta -2 +*UIConstraints: *ColorType Black&Blue *ColorBalanceMagenta -3 +*UIConstraints: *ColorType Black&Blue *ColorBalanceMagenta -4 +*UIConstraints: *ColorType Black&Blue *ColorBalanceMagenta 1 +*UIConstraints: *ColorType Black&Blue *ColorBalanceMagenta 2 +*UIConstraints: *ColorType Black&Blue *ColorBalanceMagenta 3 +*UIConstraints: *ColorType Black&Blue *ColorBalanceMagenta 4 + +*UIConstraints: *ColorType Black&Blue *ColorBalanceYellow -1 +*UIConstraints: *ColorType Black&Blue *ColorBalanceYellow -2 +*UIConstraints: *ColorType Black&Blue *ColorBalanceYellow -3 +*UIConstraints: *ColorType Black&Blue *ColorBalanceYellow -4 +*UIConstraints: *ColorType Black&Blue *ColorBalanceYellow 1 +*UIConstraints: *ColorType Black&Blue *ColorBalanceYellow 2 +*UIConstraints: *ColorType Black&Blue *ColorBalanceYellow 3 +*UIConstraints: *ColorType Black&Blue *ColorBalanceYellow 4 + +*UIConstraints: *ColorType Black&Cyan *PureBlackGray BlackAuto +*UIConstraints: *ColorType Black&Cyan *PureBlackGray BlackText +*UIConstraints: *ColorType Black&Cyan *PureBlackGray BlackTextGraphic +*UIConstraints: *ColorType Black&Cyan *PureBlackGray BlackTextGraphicImage +*UIConstraints: *ColorType Black&Cyan *PureBlackGray BlackGrayAuto +*UIConstraints: *ColorType Black&Cyan *PureBlackGray BlackGrayText +*UIConstraints: *ColorType Black&Cyan *PureBlackGray BlackGrayTextGraphic +*UIConstraints: *ColorType Black&Cyan *PureBlackGray BlackGrayTextGraphicImage + +*UIConstraints: *ColorType Black&Cyan *ColorBalanceCyan -1 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceCyan -2 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceCyan -3 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceCyan -4 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceCyan 1 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceCyan 2 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceCyan 3 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceCyan 4 + +*UIConstraints: *ColorType Black&Cyan *ColorBalanceMagenta -1 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceMagenta -2 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceMagenta -3 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceMagenta -4 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceMagenta 1 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceMagenta 2 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceMagenta 3 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceMagenta 4 + +*UIConstraints: *ColorType Black&Cyan *ColorBalanceYellow -1 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceYellow -2 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceYellow -3 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceYellow -4 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceYellow 1 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceYellow 2 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceYellow 3 +*UIConstraints: *ColorType Black&Cyan *ColorBalanceYellow 4 + +*UIConstraints: *ColorType Black&Magenta *PureBlackGray BlackAuto +*UIConstraints: *ColorType Black&Magenta *PureBlackGray BlackText +*UIConstraints: *ColorType Black&Magenta *PureBlackGray BlackTextGraphic +*UIConstraints: *ColorType Black&Magenta *PureBlackGray BlackTextGraphicImage +*UIConstraints: *ColorType Black&Magenta *PureBlackGray BlackGrayAuto +*UIConstraints: *ColorType Black&Magenta *PureBlackGray BlackGrayText +*UIConstraints: *ColorType Black&Magenta *PureBlackGray BlackGrayTextGraphic +*UIConstraints: *ColorType Black&Magenta *PureBlackGray BlackGrayTextGraphicImage + +*UIConstraints: *ColorType Black&Magenta *ColorBalanceCyan -1 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceCyan -2 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceCyan -3 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceCyan -4 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceCyan 1 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceCyan 2 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceCyan 3 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceCyan 4 + +*UIConstraints: *ColorType Black&Magenta *ColorBalanceMagenta -1 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceMagenta -2 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceMagenta -3 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceMagenta -4 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceMagenta 1 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceMagenta 2 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceMagenta 3 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceMagenta 4 + +*UIConstraints: *ColorType Black&Magenta *ColorBalanceYellow -1 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceYellow -2 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceYellow -3 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceYellow -4 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceYellow 1 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceYellow 2 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceYellow 3 +*UIConstraints: *ColorType Black&Magenta *ColorBalanceYellow 4 + +*UIConstraints: *ColorType Black&Yellow *PureBlackGray BlackAuto +*UIConstraints: *ColorType Black&Yellow *PureBlackGray BlackText +*UIConstraints: *ColorType Black&Yellow *PureBlackGray BlackTextGraphic +*UIConstraints: *ColorType Black&Yellow *PureBlackGray BlackTextGraphicImage +*UIConstraints: *ColorType Black&Yellow *PureBlackGray BlackGrayAuto +*UIConstraints: *ColorType Black&Yellow *PureBlackGray BlackGrayText +*UIConstraints: *ColorType Black&Yellow *PureBlackGray BlackGrayTextGraphic +*UIConstraints: *ColorType Black&Yellow *PureBlackGray BlackGrayTextGraphicImage + +*UIConstraints: *ColorType Black&Yellow *ColorBalanceCyan -1 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceCyan -2 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceCyan -3 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceCyan -4 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceCyan 1 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceCyan 2 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceCyan 3 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceCyan 4 + +*UIConstraints: *ColorType Black&Yellow *ColorBalanceMagenta -1 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceMagenta -2 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceMagenta -3 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceMagenta -4 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceMagenta 1 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceMagenta 2 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceMagenta 3 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceMagenta 4 + +*UIConstraints: *ColorType Black&Yellow *ColorBalanceYellow -1 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceYellow -2 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceYellow -3 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceYellow -4 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceYellow 1 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceYellow 2 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceYellow 3 +*UIConstraints: *ColorType Black&Yellow *ColorBalanceYellow 4 + +*UIConstraints: *ColorType Black&White *PureBlackGray BlackAuto +*UIConstraints: *ColorType Black&White *PureBlackGray BlackText +*UIConstraints: *ColorType Black&White *PureBlackGray BlackTextGraphic +*UIConstraints: *ColorType Black&White *PureBlackGray BlackTextGraphicImage +*UIConstraints: *ColorType Black&White *PureBlackGray BlackGrayAuto +*UIConstraints: *ColorType Black&White *PureBlackGray BlackGrayText +*UIConstraints: *ColorType Black&White *PureBlackGray BlackGrayTextGraphic +*UIConstraints: *ColorType Black&White *PureBlackGray BlackGrayTextGraphicImage + +*UIConstraints: *ColorType Black&White *ColorBalanceCyan -1 +*UIConstraints: *ColorType Black&White *ColorBalanceCyan -2 +*UIConstraints: *ColorType Black&White *ColorBalanceCyan -3 +*UIConstraints: *ColorType Black&White *ColorBalanceCyan -4 +*UIConstraints: *ColorType Black&White *ColorBalanceCyan 1 +*UIConstraints: *ColorType Black&White *ColorBalanceCyan 2 +*UIConstraints: *ColorType Black&White *ColorBalanceCyan 3 +*UIConstraints: *ColorType Black&White *ColorBalanceCyan 4 + +*UIConstraints: *ColorType Black&White *ColorBalanceMagenta -1 +*UIConstraints: *ColorType Black&White *ColorBalanceMagenta -2 +*UIConstraints: *ColorType Black&White *ColorBalanceMagenta -3 +*UIConstraints: *ColorType Black&White *ColorBalanceMagenta -4 +*UIConstraints: *ColorType Black&White *ColorBalanceMagenta 1 +*UIConstraints: *ColorType Black&White *ColorBalanceMagenta 2 +*UIConstraints: *ColorType Black&White *ColorBalanceMagenta 3 +*UIConstraints: *ColorType Black&White *ColorBalanceMagenta 4 + +*UIConstraints: *ColorType Black&White *ColorBalanceYellow -1 +*UIConstraints: *ColorType Black&White *ColorBalanceYellow -2 +*UIConstraints: *ColorType Black&White *ColorBalanceYellow -3 +*UIConstraints: *ColorType Black&White *ColorBalanceYellow -4 +*UIConstraints: *ColorType Black&White *ColorBalanceYellow 1 +*UIConstraints: *ColorType Black&White *ColorBalanceYellow 2 +*UIConstraints: *ColorType Black&White *ColorBalanceYellow 3 +*UIConstraints: *ColorType Black&White *ColorBalanceYellow 4 + +*%=== Resolution ============== + +*UIConstraints: *Resolution 600x1200dpi *ImageType Photo +*UIConstraints: *Resolution 600x1200dpi *ImageType Presentation +*UIConstraints: *Resolution 1200dpi *ImageType Photo +*UIConstraints: *Resolution 1200dpi *ImageType Presentation + +*UIConstraints: *ImageType Photo *Resolution 600x1200dpi +*UIConstraints: *ImageType Presentation *Resolution 600x1200dpi +*UIConstraints: *ImageType Photo *Resolution 1200dpi +*UIConstraints: *ImageType Presentation *Resolution 1200dpi + +*%===== Device Capabilities ========================== +*LanguageLevel: "3" + +*ColorDevice: True +*DefaultColorSpace: CMYK +*Protocols: TBCP +*TTRasterizer: Type42 +*?TTRasterizer: " + save + 42 /FontType resourcestatus + { pop pop (Type42)} {pop pop (None)} ifelse = flush + restore +" +*End + +*FreeVM: "12000000" +*LandscapeOrientation: Plus90 +*FileSystem: False +*Throughput: "35" + +*Password: "()" +*ExitServer: " + count 0 eq + { false } { true exch startjob } ifelse + not { + (WARNING: Cannot modify initial VM.) = + (Missing or invalid password.) = + (Please contact the author of this software.) = flush quit + } if +" +*End +*Reset: " + count 0 eq + { false } { true exch startjob } ifelse + not { + (WARNING: Cannot reset printer.) = + (Missing or invalid password.) = + (Please contact the author of this software.) = flush quit + } if + systemdict /quit get exec + (WARNING : Printer Reset Failed.) = flush +" +*End + +*% Commented out as per TTEC request to pass http://www.cups.org/testppd.php +*%*DefaultResolution: 600dpi +*SuggestedJobTimeout: "0" +*SuggestedWaitTimeout: "0" +*PrintPSErrors: True + + +*%===== Halftone Information ========================= +*% Commented out as per TTEC request to pass http://www.cups.org/testppd.php +*%*DefaultHalftoneType: 1 +*ScreenFreq: "85.0" +*ScreenAngle: "45.0" +*DefaultScreenProc: Dot +*ScreenProc Dot: " + { abs exch abs 2 copy add 1 gt { 1 sub dup mul exch 1 sub dup mul add 1 + sub } { dup mul exch dup mul add 1 exch sub }ifelse } +" +*End +*DefaultTransfer: Null +*Transfer Null: "{ }" +*Transfer Null.Inverse: "{ 1 exch sub }" + + +*%===== Paper Sizes ================================== +*OpenUI *PageSize: PickOne +*OrderDependency: 20 AnySetup *PageSize +*DefaultPageSize: A4 + +*PageSize A3/A3 (297 x 420mm): " + << /DeferredMediaSelection true /PageSize [842 1191] /ImagingBBox null >> setpagedevice" +*End +*PageSize A4/A4 (210 x 297mm): " + << /DeferredMediaSelection true /PageSize [595 842] /ImagingBBox null >> setpagedevice" +*End +*PageSize A5/A5 (148 x 210mm): " + << /DeferredMediaSelection true /PageSize [420 595] /ImagingBBox null >> setpagedevice" +*End +*PageSize A6/A6 (105 x 148mm): " + << /DeferredMediaSelection true /PageSize [297 420] /ImagingBBox null >> setpagedevice" +*End +*PageSize B4/B4 (257 x 364mm): " + << /DeferredMediaSelection true /PageSize [728 1032] /ImagingBBox null >> setpagedevice" +*End +*PageSize B5/B5 (182 x 257mm): " + << /DeferredMediaSelection true /PageSize [516 728] /ImagingBBox null >> setpagedevice" +*End +*PageSize Ledger/Ledger (11 x 17"): " + << /DeferredMediaSelection true /PageSize [792 1224] /ImagingBBox null >> setpagedevice" +*End +*PageSize Legal/Legal (8 1/2 x 14"): " + << /DeferredMediaSelection true /PageSize [612 1008] /ImagingBBox null >> setpagedevice" +*End +*PageSize Letter/Letter (8 1/2 x 11"): " + << /DeferredMediaSelection true /PageSize [612 792] /ImagingBBox null >> setpagedevice" +*End +*PageSize Statement/Statement (5 1/2 x 8 1/2"): " + << /DeferredMediaSelection true /PageSize [396 612] /ImagingBBox null >> setpagedevice" +*End +*PageSize Folio/Folio (210 x 330mm): " + << /DeferredMediaSelection true /PageSize [595 935] /ImagingBBox null >> setpagedevice" +*End +*PageSize Computer/Computer (10 1/8 x 14"): " + << /DeferredMediaSelection true /PageSize [729 1008] /ImagingBBox null >> setpagedevice" +*End +*PageSize LG13/13" LG (8 1/2 x 13"): " + << /DeferredMediaSelection true /PageSize [612 936] /ImagingBBox null >> setpagedevice" +*End +*PageSize SQ85/8.5" SQ (8 1/2 x 8 1/2"): " + << /DeferredMediaSelection true /PageSize [612 612] /ImagingBBox null >> setpagedevice" +*End +*PageSize Ledger-Wide/12 x 18": " + << /DeferredMediaSelection true /PageSize [865 1296] /ImagingBBox null >> setpagedevice" +*End +*PageSize 1319inch/13 x 19": " + << /DeferredMediaSelection true /PageSize [936 1368] /ImagingBBox null >> setpagedevice" +*End +*PageSize A3-Wide/305 x 457mm: " + << /DeferredMediaSelection true /PageSize [865 1297] /ImagingBBox null >> setpagedevice" +*End +*PageSize Postcard/J Post Card (100 x 148mm): " + << /DeferredMediaSelection true /PageSize [284 420] /ImagingBBox null >> setpagedevice" +*End +*PageSize DoublePostcardRotated/J Post Card DR (148 x 200mm): " + << /DeferredMediaSelection true /PageSize [420 567] /ImagingBBox null >> setpagedevice" +*End +*PageSize 8K/8K (270 x 390mm): " + << /DeferredMediaSelection true /PageSize [767 1107] /ImagingBBox null >> setpagedevice" +*End +*PageSize 16K/16K (195 x 270mm): " + << /DeferredMediaSelection true /PageSize [554 767] /ImagingBBox null >> setpagedevice" +*End +*PageSize Env9/Envelope - Com9: " + << /DeferredMediaSelection true /PageSize [279 639] /ImageBBox null >> setpagedevice" +*End +*PageSize Env10/Envelope - Com10: " + << /DeferredMediaSelection true /PageSize [297 684] /ImagingBBox null >> setpagedevice" +*End +*PageSize EnvMonarch/Envelope - Monarch: " + << /DeferredMediaSelection true /PageSize [279 540] /ImagingBBox null >> setpagedevice" +*End +*PageSize EnvPRC5/Envelope - DL: " + << /DeferredMediaSelection true /PageSize [312 624] /ImagingBBox null >> setpagedevice" +*End +*PageSize EnvChou3/Envelope - CHO3: " + << /DeferredMediaSelection true /PageSize [340 666] /ImagingBBox null >> setpagedevice" +*End +*PageSize EnvChou4/Envelope - CHO4: " + << /DeferredMediaSelection true /PageSize [255 581] /ImagingBBox null >> setpagedevice" +*End +*PageSize EnvYou4/Envelope - YOU4: " + << /DeferredMediaSelection true /PageSize [298 666] /ImagingBBox null >> setpagedevice" +*End +*PageSize EnvC5/Envelope - C5: " + << /DeferredMediaSelection true /PageSize [459 649] /ImagingBBox null >> setpagedevice" +*End +*PageSize 320450mm/320 x 450mm: " + << /DeferredMediaSelection true /PageSize [907 1276] /ImagingBBox null >> setpagedevice" +*End +*PageSize 320460mm/320 x 460mm: " + << /DeferredMediaSelection true /PageSize [907 1304] /ImagingBBox null >> setpagedevice" +*End +*PageSize LG135/13.5" LG: " + << /DeferredMediaSelection true /PageSize [612 972] /ImagingBBox null >> setpagedevice" +*End +*PageSize IndexCard/IndexCard 3x5": " + << /DeferredMediaSelection true /PageSize [216 360] /ImagingBBox null >> setpagedevice" +*End +*PageSize Executive/Executive: " + << /DeferredMediaSelection true /PageSize [522 756] /ImagingBBox null >> setpagedevice" +*End + +*?PageSize: " + save + currentpagedevice /PageSize get aload pop + 2 copy gt {exch} if + (Unknown) + 34 dict + dup [865 1297] (A3-Wide) put + dup [865 1296] (Ledger-Wide) put + dup [936 1368] (1319inch) put + dup [612 612] (SQ85) put + dup [612 936] (LG13) put + dup [729 1008] (Computer) put + dup [595 935] (Folio) put + dup [396 612] (Statement) put + dup [612 792] (Letter) put + dup [612 1008] (Legal) put + dup [792 1224] (Ledger) put + dup [516 728] (B5) put + dup [728 1032] (B4) put + dup [284 420] (Postcard) put + dup [420 567] (DoublePostcardRotated) put + dup [297 420] (A6) put + dup [420 595] (A5) put + dup [595 842] (A4) put + dup [842 1191] (A3) put + dup [554 767] (16K) put + dup [767 1107] (8K) put + dup [279 639] (Env9) put + dup [297 684] (Env10) put + dup [279 540] (EnvMonarch) put + dup [312 624] (EnvPRC5) put + dup [340 666] (EnvChou3) put + dup [255 581] (EnvChou4) put + dup [298 666] (EnvYou4) put + dup [459 649] (EnvC5) put + dup [907 1276] (SRA3) put + dup [907 1304] (320 x 460mm) put + dup [612 972] (LG135) put + dup [216 360] (IndexCard) put + dup [522 756] (Executive) put +{ exch aload pop 4 index sub abs 5 le exch + 5 index sub abs 5 le and + {exch pop exit} {pop} ifelse + } bind forall + = flush pop pop + restore +" +*End +*CloseUI: *PageSize + +*% ===== Custom Page Sizes ====== +*% min: 3.874 x 7.48 +*% max:12.00w x 18.50h +*%*MaxMediaWidth: "889" +*%*MaxMediaHeight: "3402" +*%*HWMargins: 12 12 12 12 + +*%*CustomPageSize True: " +*% 3 dict begin +*% pop +*% 2 array astore /Margins exch def +*% 2 copy gt {exch} if 2 array astore /PageSize exch def +*% /ImagingBBox null def +*% currentdict +*% end setpagedevice" +*%*End +*%*ParamCustomPageSize Width: 1 points 283 889 +*%*ParamCustomPageSize Height: 2 points 419 3402 +*%*ParamCustomPageSize WidthOffset: 3 points 0 0 +*%*ParamCustomPageSize HeightOffset: 4 points 0 0 +*%*ParamCustomPageSize Orientation: 5 int 0 0 + +*%===== Page Region ======= +*OpenUI *PageRegion: PickOne +*OrderDependency: 29 AnySetup *PageRegion +*DefaultPageRegion: A4 + +*PageRegion A3/A3 (297 x 420mm): " + << /PageSize [842 1191] /ImagingBBox null >> setpagedevice" +*End +*PageRegion A4/A4 (210 x 297mm): " + << /PageSize [595 842] /ImagingBBox null >> setpagedevice" +*End +*PageRegion A5/A5 (148 x 210mm): " + << /PageSize [420 595] /ImagingBBox null >> setpagedevice" +*End +*PageRegion A6/A6 (105 x 148mm): " + << /PageSize [297 420] /ImagingBBox null >> setpagedevice" +*End +*PageRegion B4/B4 (257 x 364mm): " + << /PageSize [728 1032] /ImagingBBox null >> setpagedevice" +*End +*PageRegion B5/B5 (182 x 257mm): " + << /PageSize [516 728] /ImagingBBox null >> setpagedevice" +*End +*PageRegion Ledger/Ledger (11 x 17"): " + << /PageSize [792 1224] /ImagingBBox null >> setpagedevice" +*End +*PageRegion Legal/Legal (8 1/2 x 14"): " + << /PageSize [612 1008] /ImagingBBox null >> setpagedevice" +*End +*PageRegion Letter/Letter (8 1/2 x 11"): " + << /PageSize [612 792] /ImagingBBox null >> setpagedevice" +*End +*PageRegion Statement/Statement (5 1/2 x 8 1/2"): " + << /PageSize [396 612] /ImagingBBox null >> setpagedevice" +*End +*PageRegion Folio/Folio (210 x 330mm): " + << /PageSize [595 935] /ImagingBBox null >> setpagedevice" +*End +*PageRegion Computer/Computer (10 1/8 x 14"): " + << /PageSize [729 1008] /ImagingBBox null >> setpagedevice" +*End +*PageRegion LG13/13" LG (8 1/2 x 13"): " + << /PageSize [612 936] /ImagingBBox null >> setpagedevice" +*End +*PageRegion SQ85/8.5" SQ (8 1/2 x 8 1/2"): " + << /PageSize [612 612] /ImagingBBox null >> setpagedevice" +*End +*PageRegion Ledger-Wide/12 x 18": " + << /PageSize [865 1296] /ImagingBBox null >> setpagedevice" +*End +*PageRegion 1319inch/13 x 19": " + << /PageSize [936 1368] /ImagingBBox null >> setpagedevice" +*End +*PageRegion A3-Wide/305 x 457mm: " + << /PageSize [865 1297] /ImagingBBox null >> setpagedevice" +*End +*PageRegion Postcard/J Post Card (100 x 148mm): " + << /PageSize [284 420] /ImagingBBox null >> setpagedevice" +*End +*PageRegion DoublePostcardRotated/J Post Card DR (148 x 200mm): " + << /PageSize [420 567] /ImagingBBox null >> setpagedevice" +*End +*PageRegion 8K/8K (270 x 390mm): " + << /PageSize [767 1107] /ImagingBBox null >> setpagedevice" +*End +*PageRegion 16K/16K (195 x 270mm): " + << /PageSize [554 767] /ImagingBBox null >> setpagedevice" +*End +*PageRegion Env9/Envelope - Com9: " + << /PageSize [279 639] /ImagingBBox null >> setpagedevice" +*End +*PageRegion Env10/Envelope - Com10: " + << /PageSize [297 684] /ImagingBBox null >> setpagedevice" +*End +*PageRegion EnvMonarch/Envelope - Monarch: " + << /PageSize [279 540] /ImagingBBox null >> setpagedevice" +*End +*PageRegion EnvPRC5/Envelope - DL: " + << /PageSize [312 624] /ImagingBBox null >> setpagedevice" +*End +*PageRegion EnvChou3/Envelope - CHO3: " + << /PageSize [340 666] /ImagingBBox null >> setpagedevice" +*End +*PageRegion EnvChou4/Envelope - CHO4: " + << /PageSize [255 581] /ImagingBBox null >> setpagedevice" +*End +*PageRegion EnvYou4/Envelope - YOU4: " + << /PageSize [298 666] /ImagingBBox null >> setpagedevice" +*End +*PageRegion EnvC5/Envelope - C5: " + << /PageSize [459 649] /ImagingBBox null >> setpagedevice" +*End +*PageRegion 320450mm/320 x 450mm: " + << /PageSize [907 1276] /ImagingBBox null >> setpagedevice" +*End +*PageRegion 320460mm/320 x 460mm: " + << /PageSize [907 1304] /ImagingBBox null >> setpagedevice" +*End +*PageRegion LG135/13.5" LG: " + << /PageSize [612 972] /ImagingBBox null >> setpagedevice" +*End +*PageRegion IndexCard/IndexCard 3x5": " + << /PageSize [216 360] /ImagingBBox null >> setpagedevice" +*End +*PageRegion Executive/Executive: " + << /PageSize [522 756] /ImagingBBox null >> setpagedevice" +*End +*CloseUI: *PageRegion + +*%===== Imageable Area ===== +*DefaultImageableArea: A4 +*ImageableArea A3/A3 (297 x 420mm): "14.16 14.16 827.84 1176.84 " +*ImageableArea A4/A4 (210 x 297mm): "14.16 14.16 581.84 827.84 " +*ImageableArea A5/A5 (148 x 210mm): "14.28 14.16 405.72 581.84 " +*ImageableArea A6/A6 (105 x 148mm): "14.16 14.28 283.84 405.72 " +*ImageableArea B4/B4 (257 x 364mm): "14.16 14.16 714.84 1017.84 " +*ImageableArea B5/B5 (182 x 257mm): "14.28 14.16 501.72 714.84 " +*ImageableArea Ledger/Ledger (11 x 17"): "14.16 14.16 776.84 1210.84 " +*ImageableArea Legal/Legal (8 1/2 x 14"): "14.16 14.16 598.84 995.84 " +*ImageableArea Letter/Letter (8 1/2 x 11"): "14.16 14.16 598.84 776.84 " +*ImageableArea Statement/Statement (5 1/2 x 8 1/2"): "14.28 14.16 382.72 598.84 " +*ImageableArea Folio/Folio (210 x 330mm): "14.16 14.16 581.84 921.84 " +*ImageableArea Computer/Computer (10 1/8 x 14"): "14.16 14.16 714.84 995.84 " +*ImageableArea LG13/13" LG (8 1/2 x 13"): "14.16 14.16 598.84 921.84 " +*ImageableArea SQ85/8.5" SQ (8 1/2 x 8 1/2"): "14.16 14.16 598.84 598.84 " +*ImageableArea Ledger-Wide/12 x 18": "36.84 35.52 828.16 1260.48 " +*ImageableArea 1319inch/13 x 19": "30.24 36.00 905.76 1332.00 " +*ImageableArea A3-Wide/305 x 457mm: "11.40 52.44 853.60 1243.56 " +*ImageableArea Postcard/J Post Card: "14.28 14.28 269.72 405.72 " +*ImageableArea DoublePostcardRotated/J Post Card DR: "14.28 14.28 405.72 552.72 " +*ImageableArea 8K/8K (270 x 390mm): "14.16 14.16 751.84 1091.84 " +*ImageableArea 16K/16K (195 x 270mm): "14.16 14.16 538.84 751.84 " +*ImageableArea Env9/Envelope - Com9: "14.16 14.16 264.84 624.84 " +*ImageableArea Env10/Envelope - Com10: "14.16 14.16 282.84 669.84 " +*ImageableArea EnvMonarch/Envelope - Monarch: "14.16 14.16 264.84 525.84 " +*ImageableArea EnvPRC5/Envelope - DL: "14.16 14.16 297.84 609.84 " +*ImageableArea EnvChou3/Envelope - CHO3: "14.16 14.16 325.84 651.84 " +*ImageableArea EnvChou4/Envelope - CHO4: "14.16 14.16 240.84 566.84 " +*ImageableArea EnvYou4/Envelope - YOU4: "14.16 14.16 283.84 651.84 " +*ImageableArea EnvC5/Envelope - C5: "14.16 14.16 444.84 634.84 " +*ImageableArea 320450mm/320 x 450mm: "27.24 20.16 879.72 1255.80 " +*ImageableArea 320460mm/320 x 460mm: "27.24 34.20 879.72 1269.84 " +*ImageableArea LG135/13.5" LG: "14.16 14.16 597.84 957.84 " +*ImageableArea IndexCard/IndexCard 3x5": "14.16 14.16 201.84 345.84 " +*ImageableArea Executive/Executive: "14.16 14.16 507.84 741.84 " + +*?ImageableArea: " + save + /cvp { ( ) cvs print ( ) print } bind def + /upperright {10000 mul floor 10000 div} bind def + /lowerleft {10000 mul ceiling 10000 div} bind def + newpath clippath pathbbox + 4 -2 roll exch 2 {lowerleft cvp} repeat + exch 2 {upperright cvp} repeat flush + restore +" +*End + +*%===== Paper Dimension ===== +*DefaultPaperDimension: A4 +*PaperDimension A3/A3 (297 x 420mm): "842 1191" +*PaperDimension A4/A4 (210 x 297mm): "595 842" +*PaperDimension A5/A5 (148 x 210mm): "420 595" +*PaperDimension A6/A6 (105 x 148mm): "297 420" +*PaperDimension B4/B4 (257 x 364mm): "728 1032" +*PaperDimension B5/B5 (182 x 257mm): "516 728" +*PaperDimension Ledger/Ledger (11 x 17"): "792 1224" +*PaperDimension Legal/Legal (8 1/2 x 14"): "612 1008" +*PaperDimension Letter/Letter (8 1/2 x 11"): "612 792" +*PaperDimension Statement/Statement (5 1/2 x 8 1/2"): "396 612" +*PaperDimension Folio/Folio (210 x 330mm): "595 935" +*PaperDimension Computer/Computer (10 1/8 x 14"): "729 1008" +*PaperDimension LG13/13" LG (8 1/2 x 13"): "612 936" +*PaperDimension SQ85/8.5" SQ (8 1/2 x 8 1/2"): "612 612" +*PaperDimension Ledger-Wide/12 x 18": "865 1296" +*PaperDimension 1319inch/13 x 19": "936 1368" +*PaperDimension A3-Wide/305 x 457mm: "865 1297" +*PaperDimension Postcard/J Post Card (100 x 148mm): "284 420" +*PaperDimension DoublePostcardRotated/J Post Card (148 x 200mm): "420 567" +*PaperDimension 8K/8K (270 x 390mm): "767 1107" +*PaperDimension 16K/16K (195 x 270mm): "554 767" +*PaperDimension Env9/Envelope - Com9: "279 639" +*PaperDimension Env10/Envelope - Com10: "297 684" +*PaperDimension EnvMonarch/Envelope - Monarch: "279 540" +*PaperDimension EnvPRC5/Envelope - DL: "312 624" +*PaperDimension EnvChou3/Envelope - CHO3: "340 666" +*PaperDimension EnvChou4/Envelope - CHO4: "255 581" +*PaperDimension EnvYou4/Envelope - YOU4: "298 666" +*PaperDimension EnvC5/Envelope - C5: "459 649" +*PaperDimension 320450mm/320 x 450mm: "907 1276" +*PaperDimension 320460mm/320 x 460mm: "907 1304" +*PaperDimension LG135/13.5" LG: "612 972" +*PaperDimension IndexCard/IndexCard 3x5": "216 360" +*PaperDimension Executive/Executive: "522 756" + +*%===== Paper Source ================================= +*OpenUI *InputSlot: PickOne +*OrderDependency: 35 AnySetup *InputSlot +*DefaultInputSlot: Auto + +*InputSlot Auto/Auto (Default): " + << /DeferredMediaSelection true /ManualFeed false /MediaPosition 9 >> setpagedevice" +*End +*InputSlot UpperCassette/Drawer 1: " + << /DeferredMediaSelection true /ManualFeed false /MediaPosition 0 >> setpagedevice" +*End +*InputSlot LowerCassette/Drawer 2: " + << /DeferredMediaSelection true /ManualFeed false /MediaPosition 1 >> setpagedevice" +*End +*InputSlot LCF/LCF: " + << /DeferredMediaSelection true /ManualFeed false /MediaPosition 4 >> setpagedevice" +*End +*InputSlot ExternalLCF/External LCF: " + << /DeferredMediaSelection true /ManualFeed false /MediaPosition 6 >> setpagedevice" +*End +*InputSlot PedestalUpperCassette/Drawer 3: " + << /DeferredMediaSelection true /ManualFeed false /MediaPosition 4 >> setpagedevice" +*End +*InputSlot PedestalLowerCassette/Drawer 4: " + << /DeferredMediaSelection true /ManualFeed false /MediaPosition 5 >> setpagedevice" +*End +*InputSlot SheetFeedBypass/Bypass Tray:" + << /DeferredMediaSelection true /ManualFeed true /MediaPosition 3 >> setpagedevice" +*End +*CloseUI: *InputSlot + +*%===== Media Type ======= + +*OpenUI *MediaType/Media Type: PickOne +*OrderDependency: 35 AnySetup *MediaType +*DefaultMediaType: None + +*MediaType None/Printer's Default: "" +*MediaType Plain/Plain: " + << /DeferredMediaSelection true /MediaType (Plain) >> setpagedevice + userdict /TSBMediaType 0 put + <> setpagedevice" +*End +*MediaType Plainback/Plain (Back): " + << /DeferredMediaSelection true /MediaType (Plainb) >> setpagedevice + userdict /TSBMediaType 1 put + <> setpagedevice" +*End +*MediaType PlainA/Plain (Auto): " + << /DeferredMediaSelection true /MediaType (Plain) >> setpagedevice + userdict /TSBMediaType 2 put + <> setpagedevice" +*End +*MediaType Plainthin/Plain (Thin): " + << /DeferredMediaSelection true /MediaType (Thin) >> setpagedevice + userdict /TSBMediaType 44 put + <> setpagedevice" +*End +*MediaType Plain1/Plain 1: " + << /DeferredMediaSelection true /MediaType (Plain1) >> setpagedevice + userdict /TSBMediaType 3 put + <> setpagedevice" +*End +*MediaType Plain2/Plain 2: " + << /DeferredMediaSelection true /MediaType (Plain2) >> setpagedevice + userdict /TSBMediaType 4 put + <> setpagedevice" +*End +*MediaType Thick1/Thick 1: " + << /DeferredMediaSelection true /MediaType (Thick 1) >> setpagedevice + userdict /TSBMediaType 5 put + <> setpagedevice" +*End +*MediaType Thick1back/Thick 1 (Back): " + << /DeferredMediaSelection true /MediaType (Thick 1b) >> setpagedevice + userdict /TSBMediaType 6 put + <> setpagedevice" +*End +*MediaType Thick2/Thick 2: " + << /DeferredMediaSelection true /MediaType (Thick 2) >> setpagedevice + userdict /TSBMediaType 7 put + <> setpagedevice" +*End +*MediaType Thick2back/Thick 2 (Back): " + << /DeferredMediaSelection true /MediaType (Thick 2b) >> setpagedevice + userdict /TSBMediaType 8 put + <> setpagedevice" +*End +*MediaType Thick3/Thick 3: " + << /DeferredMediaSelection true /MediaType (Thick 3) >> setpagedevice + userdict /TSBMediaType 9 put + <> setpagedevice" +*End +*MediaType Thick3back/Thick 3 (Back): " + << /DeferredMediaSelection true /MediaType (Thick 3b) >> setpagedevice + userdict /TSBMediaType 10 put + <> setpagedevice" +*End +*MediaType Thick4/Thick 4: " + << /DeferredMediaSelection true /MediaType (Thick 4) >> setpagedevice + userdict /TSBMediaType 11 put + <> setpagedevice" +*End +*MediaType Thick4back/Thick 4 (Back): " + << /DeferredMediaSelection true /MediaType (Thick 4b) >> setpagedevice + userdict /TSBMediaType 12 put + <> setpagedevice" +*End +*MediaType Thick5/Thick 5: " + << /DeferredMediaSelection true /MediaType (Thick 5) >> setpagedevice + userdict /TSBMediaType 34 put + <> setpagedevice" +*End +*MediaType Transparency/Transparency: " + << /DeferredMediaSelection true /MediaType (Transparency) >> setpagedevice + userdict /TSBMediaType 13 put + <> setpagedevice" +*End +*MediaType Recycled/Recycled: " + << /DeferredMediaSelection true /MediaType (Recycled) >> setpagedevice + userdict /TSBMediaType 14 put + <> setpagedevice" +*End +*MediaType Recycledback/Recycled (Back): " + << /DeferredMediaSelection true /MediaType (Recycledb) >> setpagedevice + userdict /TSBMediaType 15 put + <> setpagedevice" +*End +*MediaType Special1/Special 1: " + << /DeferredMediaSelection true /MediaType (Waterproof 1) >> setpagedevice + userdict /TSBMediaType 16 put + << /OutputPosition 3 >> setpagedevice + <> setpagedevice" +*End +*MediaType Special1back/Special 1 (Back): " + << /DeferredMediaSelection true /MediaType (Waterproof 1b) >> setpagedevice + userdict /TSBMediaType 17 put + << /OutputPosition 3 >> setpagedevice + <> setpagedevice" +*End +*MediaType Special2/Special 2: " + << /DeferredMediaSelection true /MediaType (Waterproof 2) >> setpagedevice + userdict /TSBMediaType 18 put + << /OutputPosition 3 >> setpagedevice + <> setpagedevice" +*End +*MediaType Special2back/Special 2 (Back): " + << /DeferredMediaSelection true /MediaType (Waterproof 2b) >> setpagedevice + userdict /TSBMediaType 19 put + << /OutputPosition 3 >> setpagedevice + <> setpagedevice" +*End +*MediaType Special3/Special 3: " + << /DeferredMediaSelection true /MediaType (Waterproof 3) >> setpagedevice + userdict /TSBMediaType 20 put + << /OutputPosition 3 >> setpagedevice + <> setpagedevice" +*End +*MediaType Special3back/Special 3 (Back): " + << /DeferredMediaSelection true /MediaType (Waterproof 3b) >> setpagedevice + userdict /TSBMediaType 21 put + << /OutputPosition 3 >> setpagedevice + <> setpagedevice" +*End +*MediaType Special4/Special 4: " + << /DeferredMediaSelection true /MediaType (Waterproof 4) >> setpagedevice + userdict /TSBMediaType 45 put + << /OutputPosition 3 >> setpagedevice + <> setpagedevice" +*End +*MediaType Special5/Special 5: " + << /DeferredMediaSelection true /MediaType (Waterproof 5) >> setpagedevice + userdict /TSBMediaType 46 put + << /OutputPosition 3 >> setpagedevice + <> setpagedevice" +*End +*MediaType Special6/Special 6: " + << /DeferredMediaSelection true /MediaType (Waterproof 6) >> setpagedevice + userdict /TSBMediaType 47 put + << /OutputPosition 3 >> setpagedevice + <> setpagedevice" +*End +*MediaType Tab/Tab: " + << /DeferredMediaSelection true /MediaType (Tab) >> setpagedevice + userdict /TSBMediaType 22 put + <> setpagedevice" +*End +*MediaType Thin/Thin: " + << /DeferredMediaSelection true /MediaType (Thin) >> setpagedevice + userdict /TSBMediaType 23 put + <> setpagedevice" +*End +*MediaType Thinback/Thin (Back): " + << /DeferredMediaSelection true /MediaType (Thinb) >> setpagedevice + userdict /TSBMediaType 24 put + <> setpagedevice" +*End +*MediaType Envelope/Envelope: " + << /DeferredMediaSelection true /MediaType (Envelope) >> setpagedevice + userdict /TSBMediaType 58 put + <> setpagedevice" +*End +*MediaType Envelopeback/Envelope (Back): " + << /DeferredMediaSelection true /MediaType (Envelopeb) >> setpagedevice + userdict /TSBMediaType 59 put + <> setpagedevice" +*End +*MediaType Envelope1/Envelope 1: " + << /DeferredMediaSelection true /MediaType (Envelope1) >> setpagedevice + userdict /TSBMediaType 48 put + <> setpagedevice" +*End +*MediaType Envelope2/Envelope 2: " + << /DeferredMediaSelection true /MediaType (Envelope2) >> setpagedevice + userdict /TSBMediaType 49 put + <> setpagedevice" +*End +*MediaType Envelope3/Envelope 3: " + << /DeferredMediaSelection true /MediaType (Envelope3) >> setpagedevice + userdict /TSBMediaType 50 put + <> setpagedevice" +*End +*MediaType Envelope4/Envelope 4: " + << /DeferredMediaSelection true /MediaType (Envelope4) >> setpagedevice + userdict /TSBMediaType 51 put + <> setpagedevice" +*End +*MediaType UserType1/USER TYPE 1: " + << /DeferredMediaSelection true /MediaType (UserType1) >> setpagedevice + userdict /TSBMediaType 52 put + <> setpagedevice" +*End +*MediaType UserType2/USER TYPE 2: " + << /DeferredMediaSelection true /MediaType (UserType2) >> setpagedevice + userdict /TSBMediaType 53 put + <> setpagedevice" +*End +*MediaType UserType3/USER TYPE 3: " + << /DeferredMediaSelection true /MediaType (UserType3) >> setpagedevice + userdict /TSBMediaType 54 put + <> setpagedevice" +*End +*MediaType UserType4/USER TYPE 4: " + << /DeferredMediaSelection true /MediaType (UserType4) >> setpagedevice + userdict /TSBMediaType 55 put + <> setpagedevice" +*End +*MediaType UserType5/USER TYPE 5: " + << /DeferredMediaSelection true /MediaType (UserType5) >> setpagedevice + userdict /TSBMediaType 56 put + <> setpagedevice" +*End +*CloseUI: *MediaType + + +*%===== Duplex ======================================= +*% Long and short edge duplexing options selected here override the short +*% edge duplexing that may be selected by Booklet Mode Printing options. + +*OpenUI *Duplex/Duplex: PickOne +*OrderDependency: 34 AnySetup *Duplex +*DefaultDuplex: DuplexNoTumble + +*Duplex None/1-Sided: "" +*End + +*Duplex DuplexNoTumble/2-Sided, No Tumble(Long-Edge Binding): " + << /Duplex true /Tumble false >> setpagedevice" +*End + +*Duplex DuplexTumble/2-Sided, Tumble(Short-Edge Binding): " + << /Duplex true /Tumble true >> setpagedevice" +*End + +*?Duplex: " + save + currentpagedevice /Duplex get + {currentpagedevice /Tumble get {(DuplexTumble)}{(DuplexNoTumble)}ifelse} + {(None)}ifelse + = flush + restore" +*End +*CloseUI: *Duplex + + +*%====== Collate ===================== +*% Collate must be the last OrderDependancy. + +*OpenUI *Collate/Collate: Boolean +*OrderDependency: 60 AnySetup *Collate +*DefaultCollate: True +*Collate True: " + /concat_str_str { + % parameters + % string string + % result + % string + dup length + 2 index length add + 1 index type pop string + dup 0 4 index putinterval + dup 4 -1 roll length + 4 -1 roll putinterval + } bind def + + /concat_str_num { + % parameters + % string number + 10 string + cvs + concat_str_str + } bind def + <> setpagedevice" +*End +*Collate False: " + /concat_str_str { + % parameters + % string string + % result + % string + dup length + 2 index length add + 1 index type pop string + dup 0 4 index putinterval + dup 4 -1 roll length + 4 -1 roll putinterval + } bind def + + /concat_str_num { + % parameters + % string number + 10 string + cvs + concat_str_str + } bind def + <> setpagedevice" +*End +*CloseUI: *Collate + + + +*OpenGroup: FinishingOptions/Finishing + +*%===== Destination ================================== +*OpenUI *OutputTray/Destination: PickOne +*OrderDependency: 37 AnySetup *OutputTray +*DefaultOutputTray: Auto +*OutputTray Auto/Printer's Default: " + " +*End +*OutputTray Inner/Exit Tray: " + << /OutputPosition 1 >> setpagedevice" +*End +*OutputTray InnerU/Upper Exit Tray: " + << /OutputPosition 1 >> setpagedevice" +*End +*OutputTray SideExitTray/Side Exit Tray: " + << /OutputPosition 2 >> setpagedevice" +*End +*OutputTray Bin1/Tray 1: " + << /OutputPosition 3 >> setpagedevice" +*End +*OutputTray Bin2/Tray 2: " + << /OutputPosition 4 >> setpagedevice" +*End +*CloseUI: *OutputTray + + +*%===== Hole Punch ==================================== +*OpenUI *HolePunch/Hole Punch: PickOne +*OrderDependency: 38 AnySetup *HolePunch +*DefaultHolePunch: Off + +*HolePunch Off/Off: " + <> setpagedevice" +*End +*HolePunch LEP-0R/Long Edge Punch without rotation: " + <> setpagedevice" +*End +*HolePunch SEP-0R/Short Edge Punch without rotation: " + <> setpagedevice" +*End +*HolePunch LEP-180R/Long Edge Punch with 180 degree rotation: " + <> setpagedevice" +*End +*HolePunch SEP-180R/Short Edge Punch with 180 degree rotation: " + <> setpagedevice" +*End +*CloseUI: *HolePunch + + +*%===== Stapling ==================================== +*OpenUI *Stapling/Stapling: PickOne +*OrderDependency: 39 AnySetup *Stapling +*DefaultStapling: Off + +*Stapling Off/Off: " + <> setpagedevice" +*End +*Stapling UL/Upper Left (Portrait) / Upper Right (Landscape):" + <> setpagedevice" +*End +*Stapling ML/Middle Left (Portrait) / Middle Top (Landscape):" + <> setpagedevice" +*End +*Stapling LL/Lower Left (Portrait) / Upper Left (Landscape):" + <> setpagedevice" +*End +*Stapling UR/Upper Right (Portrait) / Lower Right (Landscape):" + <> setpagedevice" +*End +*Stapling MR/Middle Right (Portrait) / Middle Bottom (Landscape):" + <> setpagedevice" +*End +*Stapling LR/Lower Right (Portrait) / Lower Left (Landscape):" + <> setpagedevice" +*End +*Stapling MT/Middle Top (Portrait) / Middle Right (Landscape):" + <> setpagedevice" +*End +*Stapling MB/Middle Bottom (Portrait) / Middle Left (Landscape):" + <> setpagedevice" +*End +*Stapling SS/Saddle Stitch (Portrait) / Saddle Stitch (Landscape):" + <> setpagedevice" +*End +*CloseUI: *Stapling + +*%===== Folding ============================ +*% This option allows the user to turn Folding feature On and Off. +*% The default value is Off. +*OpenUI *Folding/Folding: Boolean +*OrderDependency: 51 AnySetup *Folding +*DefaultFolding: False + +*Folding False/Off: " + " +*End + +*Folding True/On: " + <> setpagedevice" +*End + +*CloseUI: *Folding + +*CloseGroup: FinishingOptions + +*OpenGroup: PrintingModes/Printing Modes + +*%===== Print Mode ==================================== +*% If the dscInfo dictionary is not set using the printer driver, the +*% userlogin and job name are set to "CUPS User" and "CUPS Application" +*% respectively. If the dscinfo dictionary is set, document name and +*% user name are set as per the CUPS login name and Document name. +*% The default print mode is Normal. +*% The OrderDependency was 47 but this did not work. + +*OpenUI *PrintMode/Print Mode: PickOne +*OrderDependency: 49 AnySetup *PrintMode +*DefaultPrintMode: Normal + +*PrintMode Normal/Normal: " + <> setpagedevice + <> setpagedevice + <> setpagedevice" +*End + +*PrintMode Hold/Hold: " + <> setpagedevice + <> setpagedevice + <> setpagedevice" +*End + +*PrintMode Proof/Proof: " + <> setpagedevice + <> setpagedevice + <> setpagedevice" +*End + + +*% The private print DIN number is selected in the DIN options tab. +*PrintMode Private/Private - Password: " + <> setpagedevice + <> setpagedevice + <> setpagedevice + <> setpagedevice" +*End +*CloseUI: *PrintMode + + +*%===== Department Code ==================================== +*% This option sends the Department code to the printer. The department code is +*% calculated by adding together the five single department code digits. +*% The Department Code (DC) number is selected in the DC options tab. + +*OpenUI *DeptCode/Department Code: Boolean +*OrderDependency: 48 AnySetup *DeptCode +*DefaultDeptCode: False + +*DeptCode False/Disabled: "" + +*DeptCode True/Enabled: " + <> setpagedevice" +*End + +*CloseUI: *DeptCode + + +*%===== Toner Save ============================ +*% This option allows the user to turn Toner Save feature On and Off. The default value is Off. +*OpenUI *TonerSave/Toner Save: Boolean +*OrderDependency: 51 AnySetup *TonerSave +*DefaultTonerSave: False + +*TonerSave False/Off: " + <> setpagedevice" +*End + +*TonerSave True/On: " + <> setpagedevice" +*End + +*CloseUI: *TonerSave + + +*%===== Blank Page ============================ +*% This option allows the user to turn Blank page On and Off. The default value is Off. + +*OpenUI *BlankPage/Do not Print Blank Pages: Boolean +*OrderDependency: 55 AnySetup *BlankPage +*DefaultBlankPage: False + +*BlankPage False/Off: " + <> setpagedevice" +*End + +*BlankPage True/On: " + <> setpagedevice" +*End + +*CloseUI: *BlankPage + + +*CloseGroup: PrintingModes + +*% ===== Department Code Selection Options ====================================== +*% The Department Code (DC) group of options is needed for the CUPS PPD because +*% CUPS no longer supports RBISET to allow the user to enter custom values. The only +*% options are drop down lists and check boxes. The five drop down boxs allow the +*% user to effectively select a five digit number for the department code. +*% The department code is only used when the Department Code (DC) On options is checked +*% in the Print Mode options tab. The default DC value is 00000. + +*OpenGroup: DepartmentCode/Printing Modes DC + +*OpenUI *DCDigit1/Department Code (DC) - Digit 1: PickOne +*OrderDependency: 41 AnySetup *DCDigit1 +*DefaultDCDigit1: 0 +*DCDigit1 0/0: "userdict /DCDigit1 00000 put" +*DCDigit1 1/1: "userdict /DCDigit1 10000 put" +*DCDigit1 2/2: "userdict /DCDigit1 20000 put" +*DCDigit1 3/3: "userdict /DCDigit1 30000 put" +*DCDigit1 4/4: "userdict /DCDigit1 40000 put" +*DCDigit1 5/5: "userdict /DCDigit1 50000 put" +*DCDigit1 6/6: "userdict /DCDigit1 60000 put" +*DCDigit1 7/7: "userdict /DCDigit1 70000 put" +*DCDigit1 8/8: "userdict /DCDigit1 80000 put" +*DCDigit1 9/9: "userdict /DCDigit1 90000 put" +*CloseUI: *DCDigit1 + +*OpenUI *DCDigit2/Department Code (DC) - Digit 2: PickOne +*OrderDependency: 41 AnySetup *DCDigit2 +*DefaultDCDigit2: 0 +*DCDigit2 0/0: "userdict /DCDigit2 0000 put" +*DCDigit2 1/1: "userdict /DCDigit2 1000 put" +*DCDigit2 2/2: "userdict /DCDigit2 2000 put" +*DCDigit2 3/3: "userdict /DCDigit2 3000 put" +*DCDigit2 4/4: "userdict /DCDigit2 4000 put" +*DCDigit2 5/5: "userdict /DCDigit2 5000 put" +*DCDigit2 6/6: "userdict /DCDigit2 6000 put" +*DCDigit2 7/7: "userdict /DCDigit2 7000 put" +*DCDigit2 8/8: "userdict /DCDigit2 8000 put" +*DCDigit2 9/9: "userdict /DCDigit2 9000 put" +*CloseUI: *DCDigit2 + +*OpenUI *DCDigit3/Department Code (DC) - Digit 3: PickOne +*OrderDependency: 41 AnySetup *DCDigit3 +*DefaultDCDigit3: 0 +*DCDigit3 0/0: "userdict /DCDigit3 000 put" +*DCDigit3 1/1: "userdict /DCDigit3 100 put" +*DCDigit3 2/2: "userdict /DCDigit3 200 put" +*DCDigit3 3/3: "userdict /DCDigit3 300 put" +*DCDigit3 4/4: "userdict /DCDigit3 400 put" +*DCDigit3 5/5: "userdict /DCDigit3 500 put" +*DCDigit3 6/6: "userdict /DCDigit3 600 put" +*DCDigit3 7/7: "userdict /DCDigit3 700 put" +*DCDigit3 8/8: "userdict /DCDigit3 800 put" +*DCDigit3 9/9: "userdict /DCDigit3 900 put" +*CloseUI: *DCDigit3 + +*OpenUI *DCDigit4/Department Code (DC) - Digit 4: PickOne +*OrderDependency: 41 AnySetup *DCDigit4 +*DefaultDCDigit4: 0 +*DCDigit4 0/0: "userdict /DCDigit4 00 put" +*DCDigit4 1/1: "userdict /DCDigit4 10 put" +*DCDigit4 2/2: "userdict /DCDigit4 20 put" +*DCDigit4 3/3: "userdict /DCDigit4 30 put" +*DCDigit4 4/4: "userdict /DCDigit4 40 put" +*DCDigit4 5/5: "userdict /DCDigit4 50 put" +*DCDigit4 6/6: "userdict /DCDigit4 60 put" +*DCDigit4 7/7: "userdict /DCDigit4 70 put" +*DCDigit4 8/8: "userdict /DCDigit4 80 put" +*DCDigit4 9/9: "userdict /DCDigit4 90 put" +*CloseUI: *DCDigit4 + +*OpenUI *DCDigit5/Department Code (DC) - Digit 5: PickOne +*OrderDependency: 41 AnySetup *DCDigit5 +*DefaultDCDigit5: 0 +*DCDigit5 0/0: "userdict /DCDigit5 0 put" +*DCDigit5 1/1: "userdict /DCDigit5 1 put" +*DCDigit5 2/2: "userdict /DCDigit5 2 put" +*DCDigit5 3/3: "userdict /DCDigit5 3 put" +*DCDigit5 4/4: "userdict /DCDigit5 4 put" +*DCDigit5 5/5: "userdict /DCDigit5 5 put" +*DCDigit5 6/6: "userdict /DCDigit5 6 put" +*DCDigit5 7/7: "userdict /DCDigit5 7 put" +*DCDigit5 8/8: "userdict /DCDigit5 8 put" +*DCDigit5 9/9: "userdict /DCDigit5 9 put" +*CloseUI: *DCDigit5 + +*CloseGroup: DepartmentCode + + +*% ===== Document ID Selection Options ====================================== +*% The Document ID (DIN) group of options is needed for the CUPS PPD because +*% CUPS no longer supports RBISET to allow the user to enter custom values. The only +*% options are drop down lists and check boxes. The five drop down boxs allow the +*% user to effectively select a five digit number for the document ID. +*% The Document ID is only used when the Private Print using Document ID (DIN) option +*% is checked in the Print Mode Tab/Print Mode Option. The default DIN value is 00000. + +*OpenGroup: DINNumber/Private Document Password + +*OpenUI *DINDigit1/Password - Digit 1: PickOne +*OrderDependency: 40 AnySetup *DINDigit1 +*DefaultDINDigit1: 0 +*DINDigit1 0/0: "userdict /DINDigit1 00000 put" +*DINDigit1 1/1: "userdict /DINDigit1 10000 put" +*DINDigit1 2/2: "userdict /DINDigit1 20000 put" +*DINDigit1 3/3: "userdict /DINDigit1 30000 put" +*DINDigit1 4/4: "userdict /DINDigit1 40000 put" +*DINDigit1 5/5: "userdict /DINDigit1 50000 put" +*DINDigit1 6/6: "userdict /DINDigit1 60000 put" +*DINDigit1 7/7: "userdict /DINDigit1 70000 put" +*DINDigit1 8/8: "userdict /DINDigit1 80000 put" +*DINDigit1 9/9: "userdict /DINDigit1 90000 put" +*CloseUI: *DINDigit1 + +*OpenUI *DINDigit2/Password - Digit 2: PickOne +*OrderDependency: 40 AnySetup *DINDigit2 +*DefaultDINDigit2: 0 +*DINDigit2 0/0: "userdict /DINDigit2 0000 put" +*DINDigit2 1/1: "userdict /DINDigit2 1000 put" +*DINDigit2 2/2: "userdict /DINDigit2 2000 put" +*DINDigit2 3/3: "userdict /DINDigit2 3000 put" +*DINDigit2 4/4: "userdict /DINDigit2 4000 put" +*DINDigit2 5/5: "userdict /DINDigit2 5000 put" +*DINDigit2 6/6: "userdict /DINDigit2 6000 put" +*DINDigit2 7/7: "userdict /DINDigit2 7000 put" +*DINDigit2 8/8: "userdict /DINDigit2 8000 put" +*DINDigit2 9/9: "userdict /DINDigit2 9000 put" +*CloseUI: *DINDigit2 + +*OpenUI *DINDigit3/Password - Digit 3: PickOne +*OrderDependency: 40 AnySetup *DINDigit3 +*DefaultDINDigit3: 0 +*DINDigit3 0/0: "userdict /DINDigit3 000 put" +*DINDigit3 1/1: "userdict /DINDigit3 100 put" +*DINDigit3 2/2: "userdict /DINDigit3 200 put" +*DINDigit3 3/3: "userdict /DINDigit3 300 put" +*DINDigit3 4/4: "userdict /DINDigit3 400 put" +*DINDigit3 5/5: "userdict /DINDigit3 500 put" +*DINDigit3 6/6: "userdict /DINDigit3 600 put" +*DINDigit3 7/7: "userdict /DINDigit3 700 put" +*DINDigit3 8/8: "userdict /DINDigit3 800 put" +*DINDigit3 9/9: "userdict /DINDigit3 900 put" +*CloseUI: *DINDigit3 + +*OpenUI *DINDigit4/Password - Digit 4: PickOne +*OrderDependency: 40 AnySetup *DINDigit4 +*DefaultDINDigit4: 0 +*DINDigit4 0/0: "userdict /DINDigit4 00 put" +*DINDigit4 1/1: "userdict /DINDigit4 10 put" +*DINDigit4 2/2: "userdict /DINDigit4 20 put" +*DINDigit4 3/3: "userdict /DINDigit4 30 put" +*DINDigit4 4/4: "userdict /DINDigit4 40 put" +*DINDigit4 5/5: "userdict /DINDigit4 50 put" +*DINDigit4 6/6: "userdict /DINDigit4 60 put" +*DINDigit4 7/7: "userdict /DINDigit4 70 put" +*DINDigit4 8/8: "userdict /DINDigit4 80 put" +*DINDigit4 9/9: "userdict /DINDigit4 90 put" +*CloseUI: *DINDigit4 + +*OpenUI *DINDigit5/Password - Digit 5: PickOne +*OrderDependency: 40 AnySetup *DINDigit5 +*DefaultDINDigit5: 0 +*DINDigit5 0/0: "userdict /DINDigit5 0 put" +*DINDigit5 1/1: "userdict /DINDigit5 1 put" +*DINDigit5 2/2: "userdict /DINDigit5 2 put" +*DINDigit5 3/3: "userdict /DINDigit5 3 put" +*DINDigit5 4/4: "userdict /DINDigit5 4 put" +*DINDigit5 5/5: "userdict /DINDigit5 5 put" +*DINDigit5 6/6: "userdict /DINDigit5 6 put" +*DINDigit5 7/7: "userdict /DINDigit5 7 put" +*DINDigit5 8/8: "userdict /DINDigit5 8 put" +*DINDigit5 9/9: "userdict /DINDigit5 9 put" +*CloseUI: *DINDigit5 + +*CloseGroup: DINNumber + +*%===== Booklet Mode Options ===================================== +*% This group of options allows the user to +*% select the paper size to use for booklet mode, choose the page layout +*% and select the inner and outer margin values. Further documentation is +*% contained in the PPD specification. + +*OpenGroup: BookletModeOptions/Booklet + +*%===== Booklet Paper Size =============================== +*% This specifies the paper size to be used for booklet printing. +*% The default is None (Off). If booklet paper size is not None, then the +*% paper type selected for booklet mode will override any other paper +*% type selected. +*% The TSBPrivate key takes a string parameter that is exactly the same +*% as the parameter for th PJL COMMENT command. When the setpagedevice +*% operator is executed with the TSBPrivate key the parameter is +*% immediately passed to the DsruJobPJLParse() function in the same +*% manner as if the PJL COMMENT command had been executed. The result +*% of using this key is exactly the same as if a PJL command had been +*% used so only the RIP needs to be changed to support this operation. +*% If booklet printing is selected, then short edge duplexing by default +*% is used (Duplex=true and Tumble=true), otherwise if booklet printing +*% is not selected, then duplexing is turned off (Duplex=false). The Duplexing +*% Option can be used to override this and change to long edge duplexing +*% (Duplex=true and Tumble=false) if necessary. +*OpenUI *BookletPaperSize/Booklet Paper Size: PickOne +*OrderDependency: 30 AnySetup *BookletPaperSize +*DefaultBookletPaperSize: None +*BookletPaperSize None/None (Off): "<> setpagedevice" +*BookletPaperSize Letter/Letter: " + <> setpagedevice" +*End +*BookletPaperSize A4/A4: " + <> setpagedevice" +*End +*BookletPaperSize Legal/Legal: " + <> setpagedevice" +*End +*BookletPaperSize Statement/Statement: " + <> setpagedevice" +*End +*BookletPaperSize Ledger/Ledger: " + <> setpagedevice" +*End +*BookletPaperSize Folio/Folio: " + <> setpagedevice" +*End +*BookletPaperSize A3/A3: " + <> setpagedevice" +*End +*BookletPaperSize A5/A5: " + <> setpagedevice" +*End +*BookletPaperSize B4/B4: " + <> setpagedevice" +*End +*BookletPaperSize B5/B5: " + <> setpagedevice" +*End +*BookletPaperSize Computer/Computer: " + <> setpagedevice" +*End +*BookletPaperSize Legal-13/13" LG: " + <> setpagedevice" +*End +*BookletPaperSize Square/8.5" SQ: " + <> setpagedevice" +*End +*BookletPaperSize 8K/8K: " + <> setpagedevice" +*End +*BookletPaperSize 16K/16K: " + <> setpagedevice" +*End +*BookletPaperSize Executive/Executive: " + <> setpagedevice" +*End +*BookletPaperSize LG135/13.5" LG: " + <> setpagedevice" +*End +*CloseUI: *BookletPaperSize + +*%===== Booklet Page Layout =============================== +*% This allows the user to select the page layout of the booklet, +*% Either right to left or left to right. +*% The default is left to right. +*OpenUI *BookletPageLayout/Left to Right Page Layout: Boolean +*OrderDependency: 31 AnySetup *BookletPageLayout +*DefaultBookletPageLayout: True +*BookletPageLayout False/Right to Left: " + <> setpagedevice" +*End +*BookletPageLayout True/Left to Right: " + <> setpagedevice" +*End +*CloseUI: *BookletPageLayout + +*%===== Booklet Center Margin ============================ +*% This allows the user to select the size of the center margin (gutter), +*% in points, from the range 0 - 300. This is in addition to the center +*% margin already specified by the application. The default is Off/0 points. +*OpenUI *BookletCenterMargin/Booklet Center Margin: PickOne +*OrderDependency: 44 AnySetup *BookletCenterMargin +*DefaultBookletCenterMargin: Off +*BookletCenterMargin Off/0 points: " +<> setpagedevice" +*End +*BookletCenterMargin 3/3 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletCenterMargin 6/6 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletCenterMargin 9/9 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletCenterMargin 12/12 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletCenterMargin 15/15 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletCenterMargin 18/18 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletCenterMargin 21/21 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletCenterMargin 24/24 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletCenterMargin 27/27 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletCenterMargin 30/30 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletCenterMargin 33/33 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletCenterMargin 36/36 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*CloseUI: *BookletCenterMargin + + +*%===== Booklet Outer Margin ============================ +*% This allows the user to select the size of the outer margin (creep), +*% in points, from the range 0 - 18, which should take place for the +*% booklet. The default is Off/0 points. +*OpenUI *BookletOuterMargin/Booklet Outer Margin: PickOne +*OrderDependency: 43 AnySetup *BookletOuterMargin +*DefaultBookletOuterMargin: Off +*BookletOuterMargin Off/0 points: " +<> setpagedevice" +*End +*BookletOuterMargin 6/6 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletOuterMargin 12/12 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletOuterMargin 18/18 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletOuterMargin 24/24 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletOuterMargin 30/30 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletOuterMargin 36/36 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletOuterMargin 42/42 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletOuterMargin 48/48 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletOuterMargin 54/54 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletOuterMargin 60/60 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletOuterMargin 66/66 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*BookletOuterMargin 72/72 points: " +userdict /XYResolution get 1200 eq +{ +<> setpagedevice +}{ +<> setpagedevice +}ifelse" +*End +*CloseUI: *BookletOuterMargin + +*CloseGroup: BookletModeOptions + +*RequiresPageRegion All: True + + +*OpenGroup: ColorSettings1/Color Settings 1 + +*%===== Color Settings 1 Options ================================== +*% This group of options allows the user to change the various color +*% options available on the K2 printer. Refer to the K2 +*% Printer Driver Specification v1.00 or later for more details +*% on how the Color Settings 1 options work. + + +*%===== Color Type ============================ +*% This option allows the user to select valid combinations of Color (Color or +*% Monochrome), Resolution (Hi-res or Low-res) and document Type (General, +*% Photo, Presentation and LineArt. The default value is Color, Low-res, General. +*% Color is specified twice in the PS output - as a PS command for the RIP and as +*% a PJL comment for the engine. + +*OpenUI *ColorType/Color Type: PickOne +*OrderDependency: 50 AnySetup *ColorType +*DefaultColorType: Color + +*ColorType Auto/Auto: " +<> setpagedevice " +*End + +*ColorType Color/Color: " +<> setpagedevice " +*End + +*ColorType Mono/Mono: " +<> setpagedevice +<> setpagedevice " +*End + +*ColorType Black&Red/Black and Red: " +<> setpagedevice " +*End + +*ColorType Black&Green/Black and Green: " +<> setpagedevice " +*End + +*ColorType Black&Blue/Black and Blue: " +<> setpagedevice " +*End + +*ColorType Black&Cyan/Black and Cyan: " +<> setpagedevice " +*End + +*ColorType Black&Magenta/Black and Magenta: " +<> setpagedevice " +*End + +*ColorType Black&Yellow/Black and Yellow: " +<> setpagedevice " +*End + +*ColorType Black&White/Black and White: " +<> setpagedevice " +*End + +*CloseUI: *ColorType + +*OpenUI *Resolution/Resolution: PickOne +*OrderDependency: 42 AnySetup *Resolution +*DefaultResolution: 600dpi +*Resolution 600dpi/600 dpi: " +<> setpagedevice +userdict /XYResolution 600 put" +*End +*Resolution 1200dpi/1200 dpi: " +<> setpagedevice +userdict /XYResolution 1200 put" +*End +*Resolution 600x1200dpi/600 x 1200 dpi: " +<> setpagedevice +userdict /XYResolution 1200 put" +*End +*CloseUI: *Resolution + + + +*%===== Halftone ============================ +*% This option allows the user to choose Halfone. The default value is Auto. +*OpenUI *Halftone/Halftone: PickOne +*OrderDependency: 56 AnySetup *Halftone +*DefaultHalftone: Auto + +*Halftone Auto/Auto: " + <> setpagedevice" +*End + +*Halftone Detail/Detail: " + <> setpagedevice" +*End + +*Halftone Smooth/Smooth: " + <> setpagedevice" +*End + +*CloseUI: *Halftone + + +*%===== Distinguish Thin Lines ============================ +*% This option allows the user to turn Distinguish Thin Lines On or Off. The default value is On. +*OpenUI *DistinguishThinLines/Distinguish Thin Lines: Boolean +*OrderDependency: 54 AnySetup *DistinguishThinLines +*DefaultDistinguishThinLines: False + +*DistinguishThinLines False/Off: " + <> setpagedevice" +*End + +*DistinguishThinLines True/On: " + <> setpagedevice" +*End + +*CloseUI: *DistinguishThinLines + +*CloseGroup: ColorSettings1 + + +*OpenGroup: ColorSettings2/Color Settings 2 + +*%===== Image Type ============================ +*% This option allows the user to use the Image Type feature. The default value is General. +*OpenUI *ImageType/Image Type: PickOne +*OrderDependency: 53 AnySetup *ImageType +*DefaultImageType: General + +*ImageType General/General: " + <> setpagedevice" +*End + +*ImageType Photo/Photo: " + <> setpagedevice" +*End + +*ImageType Presentation/Presentation: " + <> setpagedevice" +*End + +*ImageType LineArt/Line Art: " + <> setpagedevice" +*End + +*CloseUI: *ImageType + +*%==== Red Seal Color Mode ============================ +*% This option allows the user to turn Red Seal Color Mode feature On and Off. +*% The default value is Off. +*OpenUI *RedSealColorMode/Red Seal Color Mode: Boolean +*OrderDependency: 51 AnySetup *RedSealColorMode +*DefaultRedSealColorMode: False +*RedSealColorMode False/Off: " + <> setpagedevice" +*End +*RedSealColorMode True/On: " + <> setpagedevice" +*End + +*CloseUI: *RedSealColorMode + +*%===== Black Over Print ============================ +*% This option allows the user to turn Black Overprint On or Off. The default value +*% is Off. It also includes the PS gamma definition required by the RIP in both options. + +*OpenUI *BlackOverPrint/Black Overprint: PickOne +*OrderDependency: 57 AnySetup *BlackOverPrint +*DefaultBlackOverPrint: Text&Graphics + +*BlackOverPrint Off/Off: " +<> setpagedevice " +*End + +*BlackOverPrint Text/Text: " +<> setpagedevice " +*End + +*BlackOverPrint Text&Graphics/Text and Graphics: " +<> setpagedevice " +*End + +*CloseUI: *BlackOverPrint + +*%==== PostScript Overprint ============================ +*% This option allows the user to turn PostScript Overprint feature On and Off. +*% The default value is Off. +*OpenUI *PostScriptOverprint/PostScript Overprint: Boolean +*OrderDependency: 51 AnySetup *PostScriptOverprint +*DefaultPostScriptOverprint: False + +*PostScriptOverprint False/Off: " + <> setpagedevice" +*End + +*PostScriptOverprint True/On: " + <> setpagedevice" +*End + +*CloseUI: *PostScriptOverprint + + +*%==== Auto Trapping ============================ +*% This option allows the user to turn Auto Trapping feature On and Off. +*% The default value is Off. +*OpenUI *AutoTrapping/Auto Trapping: Boolean +*OrderDependency: 52 AnySetup *AutoTrapping +*DefaultAutoTrapping: False + +*AutoTrapping False/Off: " + <> setpagedevice" +*End + +*AutoTrapping True/On: " + <> setpagedevice" +*End + +*CloseUI: *AutoTrapping + + + +*%===== Pure Black and Pure Gray ============================ + +*% This options allows the user to select the Pure Gray and Pure Black features. +*% The user cannot Pure Gray without also selecting Pure Black. The default value +*% is Off. +*OpenUI *PureBlackGray/Pure Black and Gray: PickOne +*OrderDependency: 58 AnySetup *PureBlackGray +*DefaultPureBlackGray: BlackGrayAuto + +*PureBlackGray Off/Off: " +<> setpagedevice +<> setpagedevice " +*End + +*PureBlackGray BlackAuto/Black - Auto: " +<> setpagedevice +<> setpagedevice " +*End + +*PureBlackGray BlackText/Black - Text: " +<> setpagedevice +<> setpagedevice " +*End + +*PureBlackGray BlackTextGraphic/Black - Text and Graphic: " +<> setpagedevice +<> setpagedevice " +*End + +*PureBlackGray BlackTextGraphicImage/Black - Text, Graphic and Image: " +<> setpagedevice +<> setpagedevice " +*End + +*PureBlackGray BlackGrayAuto/Black and Gray - Auto: " +<> setpagedevice +<> setpagedevice " +*End + +*PureBlackGray BlackGrayText/Black and Gray - Text: " +<> setpagedevice +<> setpagedevice " +*End + +*PureBlackGray BlackGrayTextGraphic/Black and Gray - Text and Graphic: " +<> setpagedevice +<> setpagedevice " +*End + +*PureBlackGray BlackGrayTextGraphicImage/Black and Gray - Text, Graphic and Image: " +<> setpagedevice +<> setpagedevice " +*End +*CloseUI: *PureBlackGray + +*CloseGroup: ColorSettings2 + + +*OpenGroup: ColorSettings3/Color Settings 3 + +*%===== Color Settings 2 Options ================================== +*% This group of options allows the user to change the various color +*% options available on the K2 printer. Refer to the K2 +*% Printer Driver Specification v1.00 or later for more details +*% on how the Color Settings 2 options work. +*% +*% To display correctly, numbers need to have 2 spaces before positive +*% and 1 space before negative number. + + +*%===== Color Balance ============================ +*% This option allows the user to select valid Color Balance. +*% The only options are drop down lists. + +*OpenUI *ColorBalanceCyan/Color Balance - Cyan: PickOne +*OrderDependency: 23 AnySetup *ColorBalanceCyan +*DefaultColorBalanceCyan: 0 + +*ColorBalanceCyan -4/ -4: " +<> setpagedevice" +*End +*ColorBalanceCyan -3/ -3: " +<> setpagedevice" +*End +*ColorBalanceCyan -2/ -2: " +<> setpagedevice" +*End +*ColorBalanceCyan -1/ -1: " +<> setpagedevice" +*End +*ColorBalanceCyan 0/ 0: " +<> setpagedevice" +*End +*ColorBalanceCyan 1/ 1: " +<> setpagedevice" +*End +*ColorBalanceCyan 2/ 2: " +<> setpagedevice" +*End +*ColorBalanceCyan 3/ 3: " +<> setpagedevice" +*End +*ColorBalanceCyan 4/ 4: " +<> setpagedevice" +*End +*CloseUI: *ColorBalanceCyan + +*OpenUI *ColorBalanceMagenta/Color Balance - Magenta: PickOne +*OrderDependency: 24 AnySetup *ColorBalanceMagenta +*DefaultColorBalanceMagenta: 0 + +*ColorBalanceMagenta -4/ -4: " +<> setpagedevice" +*End +*ColorBalanceMagenta -3/ -3: " +<> setpagedevice" +*End +*ColorBalanceMagenta -2/ -2: " +<> setpagedevice" +*End +*ColorBalanceMagenta -1/ -1: " +<> setpagedevice" +*End +*ColorBalanceMagenta 0/ 0: " +<> setpagedevice" +*End +*ColorBalanceMagenta 1/ 1: " +<> setpagedevice" +*End +*ColorBalanceMagenta 2/ 2: " +<> setpagedevice" +*End +*ColorBalanceMagenta 3/ 3: " +<> setpagedevice" +*End +*ColorBalanceMagenta 4/ 4: " +<> setpagedevice" +*End +*CloseUI: *ColorBalanceMagenta + +*OpenUI *ColorBalanceYellow/Color Balance - Yellow: PickOne +*OrderDependency: 25 AnySetup *ColorBalanceYellow +*DefaultColorBalanceYellow: 0 + +*ColorBalanceYellow -4/ -4: " +<> setpagedevice" +*End +*ColorBalanceYellow -3/ -3: " +<> setpagedevice" +*End +*ColorBalanceYellow -2/ -2: " +<> setpagedevice" +*End +*ColorBalanceYellow -1/ -1: " +<> setpagedevice" +*End +*ColorBalanceYellow 0/ 0: " +<> setpagedevice" +*End +*ColorBalanceYellow 1/ 1: " +<> setpagedevice" +*End +*ColorBalanceYellow 2/ 2: " +<> setpagedevice" +*End +*ColorBalanceYellow 3/ 3: " +<> setpagedevice" +*End +*ColorBalanceYellow 4/ 4: " +<> setpagedevice" +*End +*CloseUI: *ColorBalanceYellow + +*OpenUI *ColorBalanceBlack/Color Balance - Black: PickOne +*OrderDependency: 22 AnySetup *ColorBalanceBlack +*DefaultColorBalanceBlack: 0 + +*ColorBalanceBlack -4/ -4: " +<> setpagedevice" +*End +*ColorBalanceBlack -3/ -3: " +<> setpagedevice" +*End +*ColorBalanceBlack -2/ -2: " +<> setpagedevice" +*End +*ColorBalanceBlack -1/ -1: " +<> setpagedevice" +*End +*ColorBalanceBlack 0/ 0: " +<> setpagedevice" +*End +*ColorBalanceBlack 1/ 1: " +<> setpagedevice" +*End +*ColorBalanceBlack 2/ 2: " +<> setpagedevice" +*End +*ColorBalanceBlack 3/ 3: " +<> setpagedevice" +*End +*ColorBalanceBlack 4/ 4: " +<> setpagedevice" +*End +*CloseUI: *ColorBalanceBlack + +*CloseGroup: ColorSettings3 + + +*OpenGroup: ColorSettings4/Color Settings 4 + +*%===== Use Sharpness Filter ============================ +*% This option allows the user to turn Use Sharpness Filter feature On and Off. +*% The default value is Off. +*OpenUI *UseSharpnessFilter/Use Sharpness Filter: Boolean +*OrderDependency: 59 AnySetup *UseSharpnessFilter +*DefaultUseSharpnessFilter: True + +*UseSharpnessFilter False/Off: " + <> setpagedevice" +*End + +*UseSharpnessFilter True/On: " + " +*End + +*CloseUI: *UseSharpnessFilter + +*%===== Contrast ============================ +*% This option allows the user to select valid Contrast. +*% The only options are drop down lists. + +*OpenUI *ContrastTOS/Contrast: PickOne +*OrderDependency: 26 AnySetup *ContrastTOS +*DefaultContrastTOS: 0 + +*ContrastTOS -4/ -4: " +<> setpagedevice" +*End +*ContrastTOS -3/ -3: " +<> setpagedevice" +*End +*ContrastTOS -2/ -2: " +<> setpagedevice" +*End +*ContrastTOS -1/ -1: " +<> setpagedevice" +*End +*ContrastTOS 0/ 0: " +<> setpagedevice" +*End +*ContrastTOS 1/ 1: " +<> setpagedevice" +*End +*ContrastTOS 2/ 2: " +<> setpagedevice" +*End +*ContrastTOS 3/ 3: " +<> setpagedevice" +*End +*ContrastTOS 4/ 4: " +<> setpagedevice" +*End +*CloseUI: *ContrastTOS + +*%===== Sharpness ============================ +*% This option allows the user to select valid Sharpness. +*% The only options are drop down lists. + +*OpenUI *SharpnessTOS/Sharpness: PickOne +*OrderDependency: 27 AnySetup *SharpnessTOS +*DefaultSharpnessTOS: 0 + +*SharpnessTOS -4/ -4: " +<> setpagedevice" +*End +*SharpnessTOS -3/ -3: " +<> setpagedevice" +*End +*SharpnessTOS -2/ -2: " +<> setpagedevice" +*End +*SharpnessTOS -1/ -1: " +<> setpagedevice" +*End +*SharpnessTOS 0/ 0: " +<> setpagedevice" +*End +*SharpnessTOS 1/ 1: " +<> setpagedevice" +*End +*SharpnessTOS 2/ 2: " +<> setpagedevice" +*End +*SharpnessTOS 3/ 3: " +<> setpagedevice" +*End +*SharpnessTOS 4/ 4: " +<> setpagedevice" +*End +*CloseUI: *SharpnessTOS + +*%===== Brightness ============================ +*% This option allows the user to select valid Brightness. +*% The only options are drop down lists. + +*OpenUI *BrightnessTOS/Brightness: PickOne +*OrderDependency: 21 AnySetup *BrightnessTOS +*DefaultBrightnessTOS: 0 + +*BrightnessTOS -4/ -4: " +<> setpagedevice" +*End +*BrightnessTOS -3/ -3: " +<> setpagedevice" +*End +*BrightnessTOS -2/ -2: " +<> setpagedevice" +*End +*BrightnessTOS -1/ -1: " +<> setpagedevice" +*End +*BrightnessTOS 0/ 0: " +<> setpagedevice" +*End +*BrightnessTOS 1/ 1: " +<> setpagedevice" +*End +*BrightnessTOS 2/ 2: " +<> setpagedevice" +*End +*BrightnessTOS 3/ 3: " +<> setpagedevice" +*End +*BrightnessTOS 4/ 4: " +<> setpagedevice" +*End +*CloseUI: *BrightnessTOS + +*%===== Saturation ============================ +*% This option allows the user to select valid Saturation. +*% The only options are drop down lists. + +*OpenUI *SaturationTOS/Saturation: PickOne +*OrderDependency: 28 AnySetup *SaturationTOS +*DefaultSaturationTOS: 0 + +*SaturationTOS -4/ -4: " +<> setpagedevice" +*End +*SaturationTOS -3/ -3: " +<> setpagedevice" +*End +*SaturationTOS -2/ -2: " +<> setpagedevice" +*End +*SaturationTOS -1/ -1: " +<> setpagedevice" +*End +*SaturationTOS 0/ 0: " +<> setpagedevice" +*End +*SaturationTOS 1/ 1: " +<> setpagedevice" +*End +*SaturationTOS 2/ 2: " +<> setpagedevice" +*End +*SaturationTOS 3/ 3: " +<> setpagedevice" +*End +*SaturationTOS 4/ 4: " +<> setpagedevice" +*End +*CloseUI: *SaturationTOS + +*%===== Background Adjustment ============================ + +*% This option allows the user to select valid Background Adjustment. + +*% The only options are drop down lists. + + + +*OpenUI *BackgroundAdjustmentTOS/Background Adjustment: PickOne + +*OrderDependency: 29 AnySetup *BackgroundAdjustmentTOS + +*DefaultBackgroundAdjustmentTOS: 0 + + + +*BackgroundAdjustmentTOS -4/ -4: " + +<> setpagedevice" + +*End + +*BackgroundAdjustmentTOS -3/ -3: " + +<> setpagedevice" + +*End + +*BackgroundAdjustmentTOS -2/ -2: " + +<> setpagedevice" + +*End + +*BackgroundAdjustmentTOS -1/ -1: " + +<> setpagedevice" + +*End + +*BackgroundAdjustmentTOS 0/ 0: " + +<> setpagedevice" + +*End + +*BackgroundAdjustmentTOS 1/ 1: " + +<> setpagedevice" + +*End + +*BackgroundAdjustmentTOS 2/ 2: " + +<> setpagedevice" + +*End + +*BackgroundAdjustmentTOS 3/ 3: " + +<> setpagedevice" + +*End + +*BackgroundAdjustmentTOS 4/ 4: " + +<> setpagedevice" + +*End + +*CloseUI: *BackgroundAdjustmentTOS + +*CloseGroup: ColorSettings4 + + +*% Font Information ===================== +*DefaultFont: Courier +*Font AlbertusMT-Italic: Standard "(001.000)" Standard ROM +*Font AlbertusMT-Light: Standard "(001.000)" Standard ROM +*Font AlbertusMT: Standard "(001.000)" Standard ROM +*Font AntiqueOlive-Bold: Standard "(501.007)" Standard ROM +*Font AntiqueOlive-Compact: Standard "(501.006)" Standard ROM +*Font AntiqueOlive-Italic: Standard "(501.007)" Standard ROM +*Font AntiqueOlive-Roman: Standard "(501.006)" Standard ROM +*Font AntiqueOliveCE-Bold: Win1250 "(501.007)" ExtendedRoman ROM +*Font AntiqueOliveCE-Compact: Win1250 "(501.006)" ExtendedRoman ROM +*Font AntiqueOliveCE-Italic: Win1250 "(501.007)" ExtendedRoman ROM +*Font AntiqueOliveCE-Roman: Win1250 "(501.006)" ExtendedRoman ROM +*Font Apple-Chancery: Standard "(001.000)" Standard ROM +*Font Apple-ChanceryCE: Standard "(001.000)" Standard ROM +*Font Arial-BoldItalicMT: Standard "(501.005)" Standard ROM +*Font Arial-BoldMT: Standard "(501.005)" Standard ROM +*Font Arial-ItalicMT: Standard "(501.007)" Standard ROM +*Font ArialCE-Bold: Win1250 "(501.005)" ExtendedRoman ROM +*Font ArialCE-BoldItalic: Win1250 "(501.005)" ExtendedRoman ROM +*Font ArialCE-Italic: Win1250 "(501.007)" ExtendedRoman ROM +*Font ArialCE: Win1250 "(501.005)" ExtendedRoman ROM +*Font ArialMT: Standard "(501.005)" Standard ROM +*Font AvantGarde-Book: Standard "(501.007)" Standard ROM +*Font AvantGarde-BookOblique: Standard "(501.007)" Standard ROM +*Font AvantGarde-Demi: Standard "(501.008)" Standard ROM +*Font AvantGarde-DemiOblique: Standard "(501.008)" Standard ROM +*Font AvantGardeCE-Book: Win1250 "(501.007)" ExtendedRoman ROM +*Font AvantGardeCE-BookOblique: Win1250 "(501.007)" ExtendedRoman ROM +*Font AvantGardeCE-Demi: Win1250 "(501.008)" ExtendedRoman ROM +*Font AvantGardeCE-DemiOblique: Win1250 "(501.008)" ExtendedRoman ROM +*Font Bodoni-Bold: Standard "(501.004)" Standard ROM +*Font Bodoni-BoldItalic: Standard "(501.005)" Standard ROM +*Font Bodoni-Italic: Standard "(501.005)" Standard ROM +*Font Bodoni-Poster: Standard "(501.007)" Standard ROM +*Font Bodoni-PosterCompressed: Standard "(501.005)" Standard ROM +*Font Bodoni: Standard "(501.006)" Standard ROM +*Font BodoniCE-Bold: Win1250 "(501.004)" ExtendedRoman ROM +*Font BodoniCE-BoldItalic: Win1250 "(501.005)" ExtendedRoman ROM +*Font BodoniCE-Italic: Win1250 "(501.005)" ExtendedRoman ROM +*Font BodoniCE-Poster: Win1250 "(501.007)" ExtendedRoman ROM +*Font BodoniCE-PosterCompressed: Win1250 "(501.005)" ExtendedRoman ROM +*Font BodoniCE: Win1250 "(501.006)" ExtendedRoman ROM +*Font Bookman-Demi: Standard "(501.004)" Standard ROM +*Font Bookman-DemiItalic: Standard "(501.004)" Standard ROM +*Font Bookman-Light: Standard "(501.004)" Standard ROM +*Font Bookman-LightItalic: Standard "(501.004)" Standard ROM +*Font BookmanCE-Demi: Win1250 "(501.004)" ExtendedRoman ROM +*Font BookmanCE-DemiItalic: Win1250 "(501.004)" ExtendedRoman ROM +*Font BookmanCE-Light: Win1250 "(501.004)" ExtendedRoman ROM +*Font BookmanCE-LightItalic: Win1250 "(501.004)" ExtendedRoman ROM +*Font Carta: Special "(001.001)" Standard ROM +*Font Chicago: Standard "(501.008)" Standard ROM +*Font ChicagoCE: Win1250 "(501.008)" ExtendedRoman ROM +*Font Clarendon-Bold: Standard "(501.006)" Standard ROM +*Font Clarendon-Light: Standard "(501.007)" Standard ROM +*Font Clarendon: Standard "(501.006)" Standard ROM +*Font ClarendonCE-Bold: Win1250 "(501.006)" ExtendedRoman ROM +*Font ClarendonCE-Light: Win1250 "(501.007)" ExtendedRoman ROM +*Font ClarendonCE: Win1250 "(501.006)" ExtendedRoman ROM +*Font CooperBlack-Italic: Standard "(001.003)" Standard ROM +*Font CooperBlack: Standard "(001.003)" Standard ROM +*Font Copperplate-ThirtyThreeBC: Standard "(001.002)" Standard ROM +*Font Copperplate-ThirtyTwoBC: Standard "(001.002)" Standard ROM +*Font Coronet-Regular: Standard "(001.000)" Standard ROM +*Font CoronetCE-Regular: Standard "(001.000)" Standard ROM +*Font Courier-Bold: Standard "(501.007)" Standard ROM +*Font Courier-BoldOblique: Standard "(501.007)" Standard ROM +*Font Courier-Oblique: Standard "(501.008)" Standard ROM +*Font Courier: Standard "(501.008)" Standard ROM +*Font CourierCE-Bold: Win1250 "(501.007)" ExtendedRoman ROM +*Font CourierCE-BoldOblique: Win1250 "(501.007)" ExtendedRoman ROM +*Font CourierCE-Oblique: Win1250 "(501.008)" ExtendedRoman ROM +*Font CourierCE: Win1250 "(501.008)" ExtendedRoman ROM +*Font Eurostile-Bold: Standard "(501.006)" Standard ROM +*Font Eurostile-BoldExtendedTwo: Standard "(501.006)" Standard ROM +*Font Eurostile-ExtendedTwo: Standard "(501.006)" Standard ROM +*Font Eurostile: Standard "(501.005)" Standard ROM +*Font EurostileCE-Bold: Win1250 "(501.006)" ExtendedRoman ROM +*Font EurostileCE-BoldExtendedTwo: Win1250 "(501.006)" ExtendedRoman ROM +*Font EurostileCE-ExtendedTwo: Win1250 "(501.006)" ExtendedRoman ROM +*Font EurostileCE: Win1250 "(501.005)" ExtendedRoman ROM +*Font Geneva: Standard "(501.005)" Standard ROM +*Font GenevaCE: Win1250 "(501.005)" ExtendedRoman ROM +*Font GillSans-Bold: Standard "(501.005)" Standard ROM +*Font GillSans-BoldCondensed: Standard "(501.004)" Standard ROM +*Font GillSans-BoldItalic: Standard "(501.005)" Standard ROM +*Font GillSans-Condensed: Standard "(501.005)" Standard ROM +*Font GillSans-ExtraBold: Standard "(501.005)" Standard ROM +*Font GillSans-Italic: Standard "(501.005)" Standard ROM +*Font GillSans-Light: Standard "(501.006)" Standard ROM +*Font GillSans-LightItalic: Standard "(501.006)" Standard ROM +*Font GillSans: Standard "(501.006)" Standard ROM +*Font GillSansCE-Bold: Win1250 "(501.005)" ExtendedRoman ROM +*Font GillSansCE-BoldCondensed: Win1250 "(501.004)" ExtendedRoman ROM +*Font GillSansCE-BoldItalic: Win1250 "(501.005)" ExtendedRoman ROM +*Font GillSansCE-Condensed: Win1250 "(501.005)" ExtendedRoman ROM +*Font GillSansCE-ExtraBold: Win1250 "(501.005)" ExtendedRoman ROM +*Font GillSansCE-Italic: Win1250 "(501.005)" ExtendedRoman ROM +*Font GillSansCE-Light: Win1250 "(501.006)" ExtendedRoman ROM +*Font GillSansCE-LightItalic: Win1250 "(501.006)" ExtendedRoman ROM +*Font GillSansCE-Roman: Win1250 "(501.006)" ExtendedRoman ROM +*Font Goudy-Bold: Standard "(001.002)" Standard ROM +*Font Goudy-BoldItalic: Standard "(001.002)" Standard ROM +*Font Goudy-ExtraBold: Standard "(001.001)" Standard ROM +*Font Goudy-Italic: Standard "(001.002)" Standard ROM +*Font Goudy: Standard "(001.003)" Standard ROM +*Font Helvetica-Bold: Standard "(501.007)" Standard ROM +*Font Helvetica-BoldOblique: Standard "(501.007)" Standard ROM +*Font Helvetica-Condensed-Bold: Standard "(501.007)" Standard ROM +*Font Helvetica-Condensed-BoldObl: Standard "(501.007)" Standard ROM +*Font Helvetica-Condensed-Oblique: Standard "(501.007)" Standard ROM +*Font Helvetica-Condensed: Standard "(501.007)" Standard ROM +*Font Helvetica-Narrow-Bold: Standard "(501.007)" Standard ROM +*Font Helvetica-Narrow-BoldOblique: Standard "(501.007)" Standard ROM +*Font Helvetica-Narrow-Oblique: Standard "(501.005)" Standard ROM +*Font Helvetica-Narrow: Standard "(501.005)" Standard ROM +*Font Helvetica-Oblique: Standard "(501.005)" Standard ROM +*Font Helvetica: Standard "(501.005)" Standard ROM +*Font HelveticaCE-Bold: Win1250 "(501.007)" ExtendedRoman ROM +*Font HelveticaCE-BoldOblique: Win1250 "(501.007)" ExtendedRoman ROM +*Font HelveticaCE-Cond: Win1250 "(501.007)" ExtendedRoman ROM +*Font HelveticaCE-CondBold: Win1250 "(501.007)" ExtendedRoman ROM +*Font HelveticaCE-CondBoldObl: Win1250 "(501.007)" ExtendedRoman ROM +*Font HelveticaCE-CondObl: Win1250 "(501.007)" ExtendedRoman ROM +*Font HelveticaCE-Narrow: Win1250 "(501.005)" ExtendedRoman ROM +*Font HelveticaCE-NarrowBold: Win1250 "(501.007)" ExtendedRoman ROM +*Font HelveticaCE-NarrowBoldOblique: Win1250 "(501.007)" ExtendedRoman ROM +*Font HelveticaCE-NarrowOblique: Win1250 "(501.005)" ExtendedRoman ROM +*Font HelveticaCE-Oblique: Win1250 "(501.005)" ExtendedRoman ROM +*Font HelveticaCE: Win1250 "(501.005)" ExtendedRoman ROM +*Font HoeflerText-Black: Standard "(501.004)" Standard ROM +*Font HoeflerText-BlackItalic: Standard "(501.005)" Standard ROM +*Font HoeflerText-Italic: Standard "(501.007)" Standard ROM +*Font HoeflerText-Ornaments: Standard "(001.000)" Standard ROM +*Font HoeflerText-Regular: Standard "(501.005)" Standard ROM +*Font HoeflerTextCE-Black: Win1250 "(501.004)" ExtendedRoman ROM +*Font HoeflerTextCE-BlackItalic: Win1250 "(501.005)" ExtendedRoman ROM +*Font HoeflerTextCE-Italic: Win1250 "(501.007)" ExtendedRoman ROM +*Font HoeflerTextCE-Regular: Win1250 "(501.005)" ExtendedRoman ROM +*Font JoannaMT-Bold: Standard "(501.006)" Standard ROM +*Font JoannaMT-BoldItalic: Standard "(501.006)" Standard ROM +*Font JoannaMT-Italic: Standard "(501.006)" Standard ROM +*Font JoannaMT: Standard "(501.006)" Standard ROM +*Font JoannaMTCE-Bold: Win1250 "(501.006)" ExtendedRoman ROM +*Font JoannaMTCE-BoldItalic: Win1250 "(501.006)" ExtendedRoman ROM +*Font JoannaMTCE-Italic: Win1250 "(501.006)" ExtendedRoman ROM +*Font JoannaMTCE: Win1250 "(501.006)" ExtendedRoman ROM +*Font LetterGothic-Bold: Standard "(501.008)" Standard ROM +*Font LetterGothic-BoldSlanted: Standard "(501.007)" Standard ROM +*Font LetterGothic-Slanted: Standard "(501.007)" Standard ROM +*Font LetterGothic: Standard "(501.007)" Standard ROM +*Font LetterGothicCE-Bold: Win1250 "(501.008)" ExtendedRoman ROM +*Font LetterGothicCE-BoldSlanted: Win1250 "(501.007)" ExtendedRoman ROM +*Font LetterGothicCE-Slanted: Win1250 "(501.007)" ExtendedRoman ROM +*Font LetterGothicCE: Win1250 "(501.007)" ExtendedRoman ROM +*Font LubalinGraph-Book: Standard "(501.007)" Standard ROM +*Font LubalinGraph-BookOblique: Standard "(501.007)" Standard ROM +*Font LubalinGraph-Demi: Standard "(501.007)" Standard ROM +*Font LubalinGraph-DemiOblique: Standard "(501.007)" Standard ROM +*Font LubalinGraphCE-Book: Win1250 "(501.007)" ExtendedRoman ROM +*Font LubalinGraphCE-BookOblique: Win1250 "(501.007)" ExtendedRoman ROM +*Font LubalinGraphCE-Demi: Win1250 "(501.007)" ExtendedRoman ROM +*Font LubalinGraphCE-DemiOblique: Win1250 "(501.007)" ExtendedRoman ROM +*Font Marigold: Standard "(001.000)" Standard ROM +*Font MonaLisa-Recut: Standard "(001.000)" Standard ROM +*Font Monaco: Standard "(501.008)" Standard ROM +*Font MonacoCE: Win1250 "(501.008)" ExtendedRoman ROM +*Font NewCenturySchlbk-Bold: Standard "(501.006)" Standard ROM +*Font NewCenturySchlbk-BoldItalic: Standard "(501.006)" Standard ROM +*Font NewCenturySchlbk-Italic: Standard "(501.009)" Standard ROM +*Font NewCenturySchlbk-Roman: Standard "(501.006)" Standard ROM +*Font NewCenturySchlbkCE-Bold: Win1250 "(501.006)" ExtendedRoman ROM +*Font NewCenturySchlbkCE-BoldItalic: Win1250 "(501.006)" ExtendedRoman ROM +*Font NewCenturySchlbkCE-Italic: Win1250 "(501.009)" ExtendedRoman ROM +*Font NewCenturySchlbkCE-Roman: Win1250 "(501.006)" ExtendedRoman ROM +*Font NewYork: Standard "(501.009)" Standard ROM +*Font NewYorkCE: Win1250 "(501.009)" ExtendedRoman ROM +*Font Optima-Bold: Standard "(501.006)" Standard ROM +*Font Optima-BoldItalic: Standard "(501.007)" Standard ROM +*Font Optima-Italic: Standard "(501.008)" Standard ROM +*Font Optima: Standard "(501.008)" Standard ROM +*Font OptimaCE-Bold: Win1250 "(501.006)" ExtendedRoman ROM +*Font OptimaCE-BoldItalic: Win1250 "(501.007)" ExtendedRoman ROM +*Font OptimaCE-Italic: Win1250 "(501.008)" ExtendedRoman ROM +*Font OptimaCE-Roman: Win1250 "(501.008)" ExtendedRoman ROM +*Font Oxford: Standard "(001.000)" Standard ROM +*Font Palatino-Bold: Standard "(501.006)" Standard ROM +*Font Palatino-BoldItalic: Standard "(501.005)" Standard ROM +*Font Palatino-Italic: Standard "(501.006)" Standard ROM +*Font Palatino-Roman: Standard "(501.004)" Standard ROM +*Font PalatinoCE-Bold: Win1250 "(501.006)" ExtendedRoman ROM +*Font PalatinoCE-BoldItalic: Win1250 "(501.005)" ExtendedRoman ROM +*Font PalatinoCE-Italic: Win1250 "(501.006)" ExtendedRoman ROM +*Font PalatinoCE-Roman: Win1250 "(501.004)" ExtendedRoman ROM +*Font StempelGaramond-Bold: Standard "(501.005)" Standard ROM +*Font StempelGaramond-BoldItalic: Standard "(501.009)" Standard ROM +*Font StempelGaramond-Italic: Standard "(501.007)" Standard ROM +*Font StempelGaramond-Roman: Standard "(501.008)" Standard ROM +*Font StempelGaramondCE-Bold: Win1250 "(501.005)" ExtendedRoman ROM +*Font StempelGaramondCE-BoldItalic: Win1250 "(501.009)" ExtendedRoman ROM +*Font StempelGaramondCE-Italic: Win1250 "(501.007)" ExtendedRoman ROM +*Font StempelGaramondCE-Roman: Win1250 "(501.008)" ExtendedRoman ROM +*Font Symbol: Special "(001.007S)" Standard ROM +*Font Tekton: Standard "(001.001)" Standard ROM +*Font Times-Bold: Standard "(501.006)" Standard ROM +*Font Times-BoldItalic: Standard "(501.005)" Standard ROM +*Font Times-Italic: Standard "(501.006)" Standard ROM +*Font Times-Roman: Standard "(501.006)" Standard ROM +*Font TimesCE-Bold: Win1250 "(501.006)" ExtendedRoman ROM +*Font TimesCE-BoldItalic: Win1250 "(501.005)" ExtendedRoman ROM +*Font TimesCE-Italic: Win1250 "(501.006)" ExtendedRoman ROM +*Font TimesCE-Roman: Win1250 "(501.006)" ExtendedRoman ROM +*Font TimesNewRomanCE-Bold: Win1250 "(501.006)" ExtendedRoman ROM +*Font TimesNewRomanCE-BoldItalic: Win1250 "(501.008)" ExtendedRoman ROM +*Font TimesNewRomanCE-Italic: Win1250 "(501.008)" ExtendedRoman ROM +*Font TimesNewRomanCE: Win1250 "(501.006)" ExtendedRoman ROM +*Font TimesNewRomanPS-BoldItalicMT: Standard "(501.008)" Standard ROM +*Font TimesNewRomanPS-BoldMT: Standard "(501.006)" Standard ROM +*Font TimesNewRomanPS-ItalicMT: Standard "(501.008)" Standard ROM +*Font TimesNewRomanPSMT: Standard "(501.006)" Standard ROM +*Font Univers-Bold: Standard "(501.006)" Standard ROM +*Font Univers-BoldExt: Standard "(501.008)" Standard ROM +*Font Univers-BoldExtObl: Standard "(501.008)" Standard ROM +*Font Univers-BoldOblique: Standard "(501.006)" Standard ROM +*Font Univers-Condensed: Standard "(501.008)" Standard ROM +*Font Univers-CondensedBold: Standard "(501.007)" Standard ROM +*Font Univers-CondensedBoldOblique: Standard "(501.007)" Standard ROM +*Font Univers-CondensedOblique: Standard "(501.008)" Standard ROM +*Font Univers-Extended: Standard "(501.007)" Standard ROM +*Font Univers-ExtendedObl: Standard "(501.007)" Standard ROM +*Font Univers-Light: Standard "(501.007)" Standard ROM +*Font Univers-LightOblique: Standard "(501.007)" Standard ROM +*Font Univers-Oblique: Standard "(501.007)" Standard ROM +*Font Univers: Standard "(501.007)" Standard ROM +*Font UniversCE-Bold: Win1250 "(501.006)" ExtendedRoman ROM +*Font UniversCE-BoldExt: Win1250 "(501.008)" ExtendedRoman ROM +*Font UniversCE-BoldExtObl: Win1250 "(501.008)" ExtendedRoman ROM +*Font UniversCE-BoldOblique: Win1250 "(501.006)" ExtendedRoman ROM +*Font UniversCE-Condensed: Win1250 "(501.008)" ExtendedRoman ROM +*Font UniversCE-CondensedBold: Win1250 "(501.007)" ExtendedRoman ROM +*Font UniversCE-CondensedBoldOblique: Win1250 "(501.007)" ExtendedRoman ROM +*Font UniversCE-CondensedOblique: Win1250 "(501.008)" ExtendedRoman ROM +*Font UniversCE-Extended: Win1250 "(501.007)" ExtendedRoman ROM +*Font UniversCE-ExtendedObl: Win1250 "(501.007)" ExtendedRoman ROM +*Font UniversCE-Light: Win1250 "(501.007)" ExtendedRoman ROM +*Font UniversCE-LightOblique: Win1250 "(501.007)" ExtendedRoman ROM +*Font UniversCE-Medium: Win1250 "(501.007)" ExtendedRoman ROM +*Font UniversCE-Oblique: Win1250 "(501.007)" ExtendedRoman ROM +*Font Wingdings-Regular: UnknownEncoding "(001.000)" UnknownCharset ROM +*Font ZapfChancery-MediumItalic: Standard "(002.000)" Standard ROM +*Font ZapfChanceryCE-MediumItalic: Standard "(002.000)" Standard ROM +*Font ZapfDingbats: Special "(001.004S)" Standard ROM + +*?FontQuery: " + save + { count 1 gt + { exch dup 127 string cvs (/) print print (:) print + /Font resourcestatus {pop pop (Yes)} {(No)} ifelse = + } { exit } ifelse + } bind loop + (*) = flush + restore +" +*End + +*?FontList: " + save + (*) {cvn ==} 128 string /Font resourceforall + (*) = flush + restore +" +*End + +*% Printer Messages (verbatim from printer): +*Message: "%%[ exitserver: permanent state may be changed ]%%" +*Message: "%%[ Flushing: rest of job (to end-of-file) will be ignored ]%%" +*Message: "\FontName\ not found, using Courier" + +*% Status (format: %%[ status: ] %%) +*Status: "initializing" +*Status: "busy" +*Status: "idle" +*Status: "printing" +*Status: "waiting" + +*% Input Sources (format: %%[ status: ; source: ]%% ) +*Source: "EtherTalk" +*Source: "LocalTalk" +*Source: "Parallel" +*Source: "UniComm" + +*% Printer Error (format: %%[ PrinterError: ]%%) +*% DeviceAdjustMatrix: "[1 0 0 1 0 0]" + +*%===== Color Separation Information ================= +*DefaultColorSep: ProcessBlack.85lpi.600dpi/85 lpi / 600 dpi + +*% For 85 lpi / 600 dpi ===================== +*ColorSepScreenAngle ProcessBlack.85lpi.600dpi/85 lpi / 600 dpi: "45" +*ColorSepScreenAngle CustomColor.85lpi.600dpi/85 lpi / 600 dpi: "45" +*ColorSepScreenAngle ProcessCyan.85lpi.600dpi/85 lpi / 600 dpi: "15" +*ColorSepScreenAngle ProcessMagenta.85lpi.600dpi/85 lpi / 600 dpi: "75" +*ColorSepScreenAngle ProcessYellow.85lpi.600dpi/85 lpi / 600 dpi: "0" + +*ColorSepScreenFreq ProcessBlack.85lpi.600dpi/85 lpi / 600 dpi: "85" +*ColorSepScreenFreq CustomColor.85lpi.600dpi/85 lpi / 600 dpi: "85" +*ColorSepScreenFreq ProcessCyan.85lpi.600dpi/85 lpi / 600 dpi: "85" +*ColorSepScreenFreq ProcessMagenta.85lpi.600dpi/85 lpi / 600 dpi: "85" +*ColorSepScreenFreq ProcessYellow.85lpi.600dpi/85 lpi / 600 dpi: "85" + +*% Last Edit Date: 01 November 2013 +*% end of CUPS PPD file for TOSHIBA ColorMFP + diff --git a/site-modules/profile/templates/phabricator/phabricator-aphlict.service.erb b/site-modules/profile/templates/phabricator/phabricator-aphlict.service.erb new file mode 100644 index 00000000..612d95d3 --- /dev/null +++ b/site-modules/profile/templates/phabricator/phabricator-aphlict.service.erb @@ -0,0 +1,21 @@ +# Phabricator Notification Daemon unit file +# Managed by puppet class profile::phabricator +# Changes will be overwritten + +[Unit] +Description=Phabricator Notification Daemon +Requires=network.target mysql.service apache2.service +After=network.target mysql.service apache2.service +Before=phabricator-phd.service + +[Service] +User=<%= @phabricator_user %> +Group=<%= @phabricator_user %> +RuntimeDirectory=phabricator-aphlict +Type=forking +Environment="PATH=/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin" +ExecStart=<%= @phabricator_basepath -%>/phabricator/bin/aphlict start +ExecStop=<%= @phabricator_basepath -%>/phabricator/bin/aphlict stop + +[Install] +WantedBy=multi-user.target diff --git a/site-modules/profile/templates/phabricator/phabricator-phd.service.erb b/site-modules/profile/templates/phabricator/phabricator-phd.service.erb new file mode 100644 index 00000000..85754985 --- /dev/null +++ b/site-modules/profile/templates/phabricator/phabricator-phd.service.erb @@ -0,0 +1,20 @@ +# Phabricator Daemon unit file +# Managed by puppet class profile::phabricator +# Changes will be overwritten + +[Unit] +Description=Phabricator Daemons +Requires=network.target mysql.service apache2.service +After=network.target mysql.service apache2.service + +[Service] +User=<%= @phabricator_user %> +Group=<%= @phabricator_user %> +Type=oneshot +Environment="PATH=/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin" +ExecStart=<%= @phabricator_basepath -%>/phabricator/bin/phd start +ExecStop=<%= @phabricator_basepath -%>/phabricator/bin/phd stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/site-modules/profile/templates/phabricator/phabricator-ssh-hook.sh.erb b/site-modules/profile/templates/phabricator/phabricator-ssh-hook.sh.erb new file mode 100644 index 00000000..c8c31231 --- /dev/null +++ b/site-modules/profile/templates/phabricator/phabricator-ssh-hook.sh.erb @@ -0,0 +1,18 @@ +#!/bin/sh +# +# Phabricator SSH hook +# +# Managed by puppet class profile::phabricator +# Changes will be overwritten + +VCSUSER="<%= @phabricator_vcs_user %>" + +# NOTE: Replace this with the path to your Phabricator directory. +ROOT="<%= @phabricator_basepath %>/phabricator" + +if [ "$1" != "$VCSUSER" ]; +then + exit 1 +fi + +exec "$ROOT/bin/ssh-auth" "$@" diff --git a/site-modules/profile/templates/phabricator/phabricator-sshd.service.erb b/site-modules/profile/templates/phabricator/phabricator-sshd.service.erb new file mode 100644 index 00000000..f144b2e9 --- /dev/null +++ b/site-modules/profile/templates/phabricator/phabricator-sshd.service.erb @@ -0,0 +1,14 @@ +[Unit] +Description=Phabricator Secure Shell server +After=network.target auditd.service +ConditionPathExists=!/etc/ssh/sshd_not_to_be_run + +[Service] +EnvironmentFile=-/etc/default/ssh +ExecStart=/usr/sbin/sshd -D $SSHD_OPTS -f <%= @phabricator_ssh_config %> +ExecReload=/bin/kill -HUP $MAINPID +KillMode=process +Restart=on-failure + +[Install] +WantedBy=multi-user.target diff --git a/site-modules/profile/templates/phabricator/sshd_config.phabricator.erb b/site-modules/profile/templates/phabricator/sshd_config.phabricator.erb new file mode 100644 index 00000000..1b0035fd --- /dev/null +++ b/site-modules/profile/templates/phabricator/sshd_config.phabricator.erb @@ -0,0 +1,18 @@ +AuthorizedKeysCommand <%= @phabricator_ssh_hook %> +AuthorizedKeysCommandUser <%= @phabricator_vcs_user %> +AllowUsers <%= @phabricator_vcs_user %> + +# You may need to tweak these options, but mostly they just turn off everything +# dangerous. + +Port 22 +Protocol 2 +PermitRootLogin no +AllowAgentForwarding no +AllowTcpForwarding no +PrintMotd no +PrintLastLog no +PasswordAuthentication no +AuthorizedKeysFile none + +PidFile /var/run/sshd-phabricator.pid diff --git a/site-modules/profile/templates/postgres/pg_service.conf.erb b/site-modules/profile/templates/postgres/pg_service.conf.erb new file mode 100644 index 00000000..9594fbcc --- /dev/null +++ b/site-modules/profile/templates/postgres/pg_service.conf.erb @@ -0,0 +1,6 @@ +# This file is managed by puppet. Local modifications will be overwritten. + +[swh] +dbname=softwareheritage +host=db.internal.softwareheritage.org +user=guest diff --git a/site-modules/profile/templates/prometheus/node/prometheus-node-exporter.defaults.erb b/site-modules/profile/templates/prometheus/node/prometheus-node-exporter.defaults.erb new file mode 100644 index 00000000..f7ca9665 --- /dev/null +++ b/site-modules/profile/templates/prometheus/node/prometheus-node-exporter.defaults.erb @@ -0,0 +1,134 @@ +# Set the command-line arguments to pass to the server. +# Due to shell scaping, to pass backslashes for regexes, you need to double +# them (\\d for \d). If running under systemd, you need to double them again +# (\\\\d to mean \d), and escape newlines too. +ARGS="\ +<%- scope.call_function('flatten_to_argument_list', [@defaults_config]).each do |argument| -%> + <%= argument %> \ +<%- end -%> +" + +# Prometheus-node-exporter supports the following options: +# +# --collector.diskstats.ignored-devices="^(ram|loop|fd|(h|s|v|xv)d[a-z]|nvme\\d+n\\d+p)\\d+$" +# Regexp of devices to ignore for diskstats. +# --collector.filesystem.ignored-mount-points="^/(sys|proc|dev)($|/)" +# Regexp of mount points to ignore for filesystem +# collector. +# --collector.filesystem.ignored-fs-types="^(sys|proc|auto)fs$" +# Regexp of filesystem types to ignore for +# filesystem collector. +# --collector.megacli.command="megacli" +# Command to run megacli. +# --collector.netdev.ignored-devices="^$" +# Regexp of net devices to ignore for netdev +# collector. +# --collector.ntp.server="127.0.0.1" +# NTP server to use for ntp collector +# --collector.ntp.protocol-version=4 +# NTP protocol version +# --collector.ntp.server-is-local +# Certify that collector.ntp.server address is the +# same local host as this collector. +# --collector.ntp.ip-ttl=1 IP TTL to use while sending NTP query +# --collector.ntp.max-distance=3.46608s +# Max accumulated distance to the root +# --collector.ntp.local-offset-tolerance=1ms +# Offset between local clock and local ntpd time +# to tolerate +# --path.procfs="/proc" procfs mountpoint. +# --path.sysfs="/sys" sysfs mountpoint. +# --collector.qdisc.fixtures="" +# test fixtures to use for qdisc collector +# end-to-end testing +# --collector.runit.servicedir="/etc/service" +# Path to runit service directory. +# --collector.supervisord.url="http://localhost:9001/RPC2" +# XML RPC endpoint. +# --collector.systemd.unit-whitelist=".+" +# Regexp of systemd units to whitelist. Units must +# both match whitelist and not match blacklist to +# be included. +# --collector.systemd.unit-blacklist=".+\\.scope" +# Regexp of systemd units to blacklist. Units must +# both match whitelist and not match blacklist to +# be included. +# --collector.systemd.private +# Establish a private, direct connection to +# systemd without dbus. +# --collector.textfile.directory="" +# Directory to read text files with metrics from. +# --collector.wifi.fixtures="" +# test fixtures to use for wifi collector metrics +# --collector.arp Enable the arp collector (default: enabled). +# --collector.bcache Enable the bcache collector (default: enabled). +# --collector.bonding Enable the bonding collector (default: +# disabled). +# --collector.buddyinfo Enable the buddyinfo collector (default: +# disabled). +# --collector.conntrack Enable the conntrack collector (default: +# enabled). +# --collector.cpu Enable the cpu collector (default: enabled). +# --collector.diskstats Enable the diskstats collector (default: +# enabled). +# --collector.drbd Enable the drbd collector (default: disabled). +# --collector.edac Enable the edac collector (default: enabled). +# --collector.entropy Enable the entropy collector (default: enabled). +# --collector.filefd Enable the filefd collector (default: enabled). +# --collector.filesystem Enable the filesystem collector (default: +# enabled). +# --collector.gmond Enable the gmond collector (default: disabled). +# --collector.hwmon Enable the hwmon collector (default: enabled). +# --collector.infiniband Enable the infiniband collector (default: +# enabled). +# --collector.interrupts Enable the interrupts collector (default: +# disabled). +# --collector.ipvs Enable the ipvs collector (default: enabled). +# --collector.ksmd Enable the ksmd collector (default: disabled). +# --collector.loadavg Enable the loadavg collector (default: enabled). +# --collector.logind Enable the logind collector (default: disabled). +# --collector.mdadm Enable the mdadm collector (default: enabled). +# --collector.megacli Enable the megacli collector (default: +# disabled). +# --collector.meminfo Enable the meminfo collector (default: enabled). +# --collector.meminfo_numa Enable the meminfo_numa collector (default: +# disabled). +# --collector.mountstats Enable the mountstats collector (default: +# disabled). +# --collector.netdev Enable the netdev collector (default: enabled). +# --collector.netstat Enable the netstat collector (default: enabled). +# --collector.nfs Enable the nfs collector (default: disabled). +# --collector.ntp Enable the ntp collector (default: disabled). +# --collector.qdisc Enable the qdisc collector (default: disabled). +# --collector.runit Enable the runit collector (default: disabled). +# --collector.sockstat Enable the sockstat collector (default: +# enabled). +# --collector.stat Enable the stat collector (default: enabled). +# --collector.supervisord Enable the supervisord collector (default: +# disabled). +# --collector.systemd Enable the systemd collector (default: +# disabled). +# --collector.tcpstat Enable the tcpstat collector (default: +# disabled). +# --collector.textfile Enable the textfile collector (default: +# enabled). +# --collector.time Enable the time collector (default: enabled). +# --collector.uname Enable the uname collector (default: enabled). +# --collector.vmstat Enable the vmstat collector (default: enabled). +# --collector.wifi Enable the wifi collector (default: enabled). +# --collector.xfs Enable the xfs collector (default: enabled). +# --collector.zfs Enable the zfs collector (default: enabled). +# --collector.timex Enable the timex collector (default: enabled). +# --web.listen-address=":9100" +# Address on which to expose metrics and web +# interface. +# --web.telemetry-path="/metrics" +# Path under which to expose metrics. +# --log.level="info" Only log messages with the given severity or +# above. Valid levels: [debug, info, warn, error, +# fatal] +# --log.format="logger:stderr" +# Set the log target and format. Example: +# "logger:syslog?appname=bob&local=7" or +# "logger:stdout?json=true" +# --version Show application version. diff --git a/site-modules/profile/templates/prometheus/server/prometheus.defaults.erb b/site-modules/profile/templates/prometheus/server/prometheus.defaults.erb new file mode 100644 index 00000000..b94327de --- /dev/null +++ b/site-modules/profile/templates/prometheus/server/prometheus.defaults.erb @@ -0,0 +1,61 @@ +# Set the command-line arguments to pass to the server. +ARGS="\ +<%- scope.call_function('flatten_to_argument_list', [@defaults_config]).each do |argument| -%> + <%= argument %> \ +<%- end -%> +" + +# Prometheus supports the following options: +# --config.file="/etc/prometheus/prometheus.yml" +# Prometheus configuration file path. +# --web.listen-address="0.0.0.0:9090" +# Address to listen on for UI, API, and telemetry. +# --web.read-timeout=5m Maximum duration before timing out read of the +# request, and closing idle connections. +# --web.max-connections=512 Maximum number of simultaneous connections. +# --web.external-url= The URL under which Prometheus is externally +# reachable (for example, if Prometheus is served +# via a reverse proxy). Used for generating +# relative and absolute links back to Prometheus +# itself. If the URL has a path portion, it will +# be used to prefix all HTTP endpoints served by +# Prometheus. If omitted, relevant URL components +# will be derived automatically. +# --web.route-prefix= Prefix for the internal routes of web endpoints. +# Defaults to path of --web.external-url. +# --web.local-assets="/usr/share/prometheus/web/" +# Path to static asset/templates directory. +# --web.user-assets= Path to static asset directory, available at +# /user. +# --web.enable-lifecycle Enable shutdown and reload via HTTP request. +# --web.enable-admin-api Enables API endpoints for admin control actions. +# --web.console.templates="/etc/prometheus/consoles" +# Path to the console template directory, +# available at /consoles. +# --web.console.libraries="/etc/prometheus/console_libraries" +# Path to the console library directory. +# --storage.tsdb.path="/var/lib/prometheus/metrics2/" +# Base path for metrics storage. +# --storage.tsdb.min-block-duration=2h +# Minimum duration of a data block before being +# persisted. +# --storage.tsdb.max-block-duration= +# Maximum duration compacted blocks may span. +# (Defaults to 10% of the retention period) +# --storage.tsdb.retention=15d +# How long to retain samples in the storage. +# --storage.tsdb.no-lockfile +# Do not create lockfile in data directory. +# --alertmanager.notification-queue-capacity=10000 +# The capacity of the queue for pending alert +# manager notifications. +# --alertmanager.timeout=10s +# Timeout for sending alerts to Alertmanager. +# --query.lookback-delta=5m The delta difference allowed for retrieving +# metrics during expression evaluations. +# --query.timeout=2m Maximum time a query may take before being +# aborted. +# --query.max-concurrency=20 +# Maximum number of queries executed concurrently. +# --log.level=info Only log messages with the given severity or +# above. One of: [debug, info, warn, error] diff --git a/site-modules/profile/templates/prometheus/sql/prometheus-sql-exporter.defaults.erb b/site-modules/profile/templates/prometheus/sql/prometheus-sql-exporter.defaults.erb new file mode 100644 index 00000000..c5cddbec --- /dev/null +++ b/site-modules/profile/templates/prometheus/sql/prometheus-sql-exporter.defaults.erb @@ -0,0 +1,12 @@ + +CONFIG=/etc/prometheus-sql-exporter.yml +PGHOST=/var/run/postgresql +PGAPPNAME=prometheus-sql-exporter +GOGC=40 +GOMAXPROCS=4 +LOGLEVEL=WARN +ARGS="\ +<%- scope.call_function('flatten_to_argument_list', [@defaults_config]).each do |argument| -%> + <%= argument %> \ +<%- end -%> +" diff --git a/site-modules/profile/templates/prometheus/sql/prometheus-sql-exporter.yml.in.erb b/site-modules/profile/templates/prometheus/sql/prometheus-sql-exporter.yml.in.erb new file mode 100644 index 00000000..75c3f445 --- /dev/null +++ b/site-modules/profile/templates/prometheus/sql/prometheus-sql-exporter.yml.in.erb @@ -0,0 +1,515 @@ +--- +jobs: +# These checks are done for every cluster +- name: "cluster" + interval: '0' + connections: + # We have to omit the hostname, we use PGHOST as environment variable. + # See /etc/default/prometheus-sql-exporter + - 'postgres://postgres@/postgres?sslmode=disable' + queries: + - name: "running_queries" + help: "Number of running queries" + labels: + - "datname" + - "usename" + values: + - "count" + query: | + SELECT datname::text, usename::text, COUNT(*)::float AS count + FROM pg_stat_activity + WHERE NOT datname ~ '^template(0|1)$' + GROUP BY datname, usename; + - name: "pg_stat_activity" + help: "Running Backends by Database and state" + labels: + - "datname" + - "state" + values: + - "count" + - "max_tx_duration" + query: | + SELECT + pg_database.datname::text, + tmp.state::text, + COALESCE(count,0) as count, + COALESCE(max_tx_duration,0) as max_tx_duration + FROM + ( + VALUES ('active'), + ('idle'), + ('idle in transaction'), + ('idle in transaction (aborted)'), + ('fastpath function call'), + ('disabled') + ) AS tmp(state) CROSS JOIN pg_database + LEFT JOIN + ( + SELECT + datname, + state, + count(*) AS count, + MAX(EXTRACT(EPOCH FROM now() - xact_start))::float AS max_tx_duration + FROM pg_stat_activity + GROUP BY datname,state) AS tmp2 + ON tmp.state = tmp2.state AND pg_database.datname = tmp2.datname + WHERE NOT pg_database.datname ~ '^template(0|1)$' + - name: "settings" + help: "PostgreSQL settings" + labels: + - "settings" + values: + - "max_connections" + - "autovacuum_freeze_max_age" + - "superuser_reserved_connections" + - "max_wal_senders" + - "max_prepared_transactions" + query: | + SELECT + current_setting('max_connections')::float AS max_connections, + current_setting('autovacuum_freeze_max_age')::float AS autovacuum_freeze_max_age, + current_setting('superuser_reserved_connections')::float AS superuser_reserved_connections, + current_setting('max_wal_senders')::float AS max_wal_senders, + current_setting('max_prepared_transactions')::float AS max_prepared_transactions; + - name: "pg_locks_sum" + help: "number of current locks" + labels: + - "mode" + values: + - "count" + query: | + SELECT t.mode, count(*) + FROM + (VALUES + ('AccessShareLock'), + ('RowShareLock'), + ('RowExclusiveLock'), + ('ShareUpdateExclusiveLock'), + ('ShareLock'), + ('ShareRowExclusiveLock'), + ('ExclusiveLock'), + ('AccessExclusiveLock') + ) t(mode) + FULL JOIN pg_locks l ON t.mode = l.mode GROUP BY 1; + - name: "pg_stat_database" + help: "Database statistics" + type: "counter" + labels: + - "datname" + values: + - "numbackends:count" + - "xact_commit" + - "xact_rollback" + - "blks_read" + - "blks_hit" + - "tup_returned" + - "tup_fetched" + - "tup_inserted" + - "tup_updated" + - "tup_deleted" + - "conflicts" + - "temp_files" + - "temp_bytes" + - "deadlocks" + - "blk_read_time" + - "blk_write_time" + - "freeze_age" + - "dbsize" + query: | + SELECT + s.datname::text, + numbackends::float, + xact_commit::float, + xact_rollback::float, + blks_read::float, + blks_hit::float, + tup_returned::float, + tup_fetched::float, + tup_inserted::float, + tup_updated::float, + tup_deleted::float, + conflicts::float, + temp_files::float, + temp_bytes::float, + deadlocks::float, + blk_read_time, + blk_write_time, + age(d.datfrozenxid) AS freeze_age, + pg_database_size(s.datname)::float AS dbsize + FROM pg_stat_database s + LEFT JOIN pg_database d ON d.datname = s.datname + WHERE NOT s.datname ~ '^template(0|1)$' + - name: "pg_stat_archiver" + help: "pg_stat_archiver" + values: + - "archived_count" + - "last_archived_time" + - "failed_count" + - "last_failed_time" + - "stats_reset" + query: | + SELECT + archived_count, + EXTRACT(EPOCH FROM last_archived_time), + failed_count, + EXTRACT(EPOCH FROM last_failed_time), + EXTRACT(EPOCH FROM stats_reset) + FROM pg_stat_archiver + - name: "checkpoints" + help: "Requested and timed Checkpoints" + values: + - "timed" + - "requested" + query: | + SELECT + pg_stat_get_bgwriter_timed_checkpoints() timed, + pg_stat_get_bgwriter_requested_checkpoints() requested; + - name: "txid" + help: "current txid" + values: + - "txid_current" + query: | + SELECT + txid_current(); + - name: "pg_stat_statements" + help: "pg_stat_statements" + labels: + - "usename" + - "datname" + - "queryid" + - "query" + values: + - "calls" + - "total_time" + - "rows" + - "shared_blks_hit" + - "shared_blks_read" + - "shared_blks_dirtied" + - "shared_blks_writte" + - "local_blks_hit" + - "local_blks_read" + - "local_blks_dirtied" + - "local_blks_writte" + - "temp_blks_read" + - "temp_blks_written" + query: | + WITH w_pg_stat_statements AS ( + SELECT * FROM pg_stat_statements + ) + (SELECT + usename::text + , datname::text + , queryid::text + , substr(regexp_replace(query, E'[\\n\\r]+', ' ', 'g' ),1,1024) AS query + , calls + , total_time + , rows + , shared_blks_hit + , shared_blks_read + , shared_blks_dirtied + , shared_blks_written + , local_blks_hit + , local_blks_read + , local_blks_dirtied + , local_blks_written + , temp_blks_read + , temp_blks_written + FROM w_pg_stat_statements pss + JOIN pg_database pd + ON pss.dbid = pd.oid + JOIN pg_user pu + ON pss.userid = pu.usesysid + ORDER BY pss.total_time DESC + LIMIT 25) + UNION + SELECT + usename::text + , datname::text + , queryid::text + , substr(regexp_replace(query, E'[\\n\\r]+', ' ', 'g' ),1,1024) AS query + , calls + , total_time + , rows + , shared_blks_hit + , shared_blks_read + , shared_blks_dirtied + , shared_blks_written + , local_blks_hit + , local_blks_read + , local_blks_dirtied + , local_blks_written + , temp_blks_read + , temp_blks_written + FROM w_pg_stat_statements pss2 + JOIN pg_database pd2 + ON pss2.dbid = pd2.oid + JOIN pg_user pu2 + ON pss2.userid = pu2.usesysid + ORDER BY calls DESC + LIMIT 25; + - name: "prepared_transactions" + help: "Prepared Transactions" + labels: + - "datname" + values: + - "count" + query: | + SELECT + datname::text, + COUNT(transaction) AS count + FROM pg_database d + LEFT JOIN pg_prepared_xacts x ON d.datname = x.database + WHERE NOT d.datname ~ '^template(0|1)$' + GROUP BY datname + +- name: "cluster_9" + interval: '0' + min_version: "9.0" + max_version: "9.6" + connections: + # We have to omit the hostname, we use PGHOST as environment variable. + # See /etc/default/prometheus-sql-exporter + queries: + - name: "pg_stat_replication" + help: "pg_stat_replication" + labels: + - "application_name" + - "usename" + - "client_addr" + - "client_port" + values: + - "pid" + - "current_xlog_location_bytes" + - "sent_location_bytes" + - "flush_location_bytes" + - "replay_location_bytes" + - "send_lag_bytes" + - "flush_lag_bytes" + - "replay_lag_bytes" + query: | + SELECT + COALESCE(pid, 0) AS pid, + COALESCE(application_name, ' ')::text AS application_name, + COALESCE(usename, ' ')::text AS usename, + COALESCE(client_addr::text, 'local')::text AS client_addr, + COALESCE(client_port::text, ' ') AS client_port, + COALESCE(pg_xlog_location_diff(pg_current_xlog_location(), '0/0'), 0) AS current_xlog_location_bytes, + COALESCE(pg_xlog_location_diff(sent_location, '0/0'), 0) AS sent_location_bytes, + COALESCE(pg_xlog_location_diff(flush_location, '0/0'), 0) AS flush_location_bytes, + COALESCE(pg_xlog_location_diff(replay_location, '0/0'), 0) AS replay_location_bytes, + COALESCE(pg_xlog_location_diff(pg_current_xlog_location(), sent_location), 0) AS send_lag_bytes, + COALESCE(pg_xlog_location_diff(pg_current_xlog_location(), flush_location), 0) AS flush_lag_bytes, + COALESCE(pg_xlog_location_diff(pg_current_xlog_location(), replay_location), 0) AS replay_lag_bytes + FROM pg_stat_replication LEFT JOIN (VALUES(0)) filler(i) ON TRUE + - name: "waldistance" + help: "amount of wal written since creation" + values: + - "location" + query: | + SELECT + pg_xlog_location_diff(pg_current_xlog_location(),'0/0000') "location"; + - name: "LastCheckpointDistance" + help: "Distance to the last checkpoint" + values: + - "distance" + query: | + SELECT + pg_xlog_location_diff( pg_current_xlog_location(), checkpoint_location) "distance" FROM pg_control_checkpoint(); + - name: "archive_ready" + help: "archive_ready" + values: + - "archive_ready" + query: | + SELECT COUNT(1) AS archive_ready FROM pg_ls_dir('./pg_xlog/archive_status') WHERE pg_ls_dir ~ '^[0-9a-fA-F]{24}\.ready$'; + + +- name: "cluster_10" + interval: '0' + min_version: "10" + max_version: "999999" + connections: + # We have to omit the hostname, we use PGHOST as environment variable. + # See /etc/default/prometheus-sql-exporter + queries: + - name: "pg_stat_replication" + help: "pg_stat_replication" + labels: + - "application_name" + - "usename" + - "client_addr" + - "client_port" + values: + - "pid" + - "current_xlog_lsn_bytes" + - "sent_lsn_bytes" + - "flush_lsn_bytes" + - "replay_lsn_bytes" + - "send_lag_bytes" + - "flush_lag_bytes" + - "replay_lag_bytes" + query: | + SELECT + COALESCE(pid, 0) AS pid, + COALESCE(application_name, ' ')::text AS application_name, + COALESCE(usename, ' ')::text AS usename, + COALESCE(client_addr::text, 'local')::text AS client_addr, + COALESCE(client_port::text, ' ') AS client_port, + COALESCE(pg_wal_lsn_diff(pg_current_wal_lsn(), '0/0'), 0) AS current_xlog_lsn_bytes, + COALESCE(pg_wal_lsn_diff(sent_lsn, '0/0'), 0) AS sent_location_bytes, + COALESCE(pg_wal_lsn_diff(flush_lsn, '0/0'), 0) AS flush_location_bytes, + COALESCE(pg_wal_lsn_diff(replay_lsn, '0/0'), 0) AS replay_location_bytes, + COALESCE(pg_wal_lsn_diff(pg_current_wal_lsn(), sent_lsn), 0) AS send_lag_bytes, + COALESCE(pg_wal_lsn_diff(pg_current_wal_lsn(), flush_lsn), 0) AS flush_lag_bytes, + COALESCE(pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn), 0) AS replay_lag_bytes + FROM pg_stat_replication FULL JOIN (VALUES(0)) filler(i) ON TRUE + - name: "waldistance" + help: "amount of wal written since creation" + values: + - "location" + query: | + SELECT + pg_wal_lsn_diff(pg_current_wal_lsn(),'0/0000') "location"; + - name: "LastCheckpointDistance" + help: "Distance to the last checkpoint" + values: + - "distance" + query: | + SELECT + pg_wal_lsn_diff( pg_current_wal_lsn(), checkpoint_lsn) "distance" FROM pg_control_checkpoint(); + - name: "archive_ready" + help: "archive_ready" + values: + - "archive_ready" + query: | + SELECT COUNT(1) AS archive_ready FROM pg_ls_dir('./pg_wal/archive_status') WHERE pg_ls_dir ~ '^[0-9a-fA-F]{24}\.ready$'; + +# This checks are done for every database +- name: "database" + interval: '24h' + connections: + # We have to omit the hostname, we use PGHOST as environment variable. + # See /etc/default/prometheus-sql-exporter + - 'postgres://postgres@/postgres?sslmode=disable' + queries: + - name: "CREATE EXTENSION pg_stat_statements" + help: "Creates the needed extension pg_stat_statements and does not produce errors." + query: | + DO $$ + BEGIN + EXECUTE 'CREATE EXTENSION pg_stat_statements'; + EXCEPTION WHEN OTHERS THEN + RETURN; + END; + $$; +- name: "database" + interval: '0' + connections: + # We have to omit the hostname, we use PGHOST as environment variable. + # See /etc/default/prometheus-sql-exporter + - 'postgres://postgres@/postgres?sslmode=disable' + queries: + - name: "pg_stat_user_tables" + help: "Table stats" + labels: + - "datname" + - "schemaname" + - "relname" + values: + - "seq_scan" + - "seq_tup_read" + - "idx_scan" + - "idx_tup_fetch" + - "n_tup_ins" + - "n_tup_upd" + - "n_tup_del" + - "n_tup_hot_upd" + - "n_live_tup" + - "n_dead_tup" + - "vacuum_count" + - "autovacuum_count" + - "analyze_count" + - "autoanalyze_count" + query: | + SELECT + current_database()::text AS datname + , coalesce(schemaname::text, 'null') AS schemaname + , coalesce(relname::text, 'null') AS relname + , coalesce(seq_scan,0)::float AS seq_scan + , coalesce(seq_tup_read,0)::float AS seq_tup_read + , coalesce(idx_scan,0)::float AS idx_scan + , coalesce(idx_tup_fetch,0)::float AS idx_tup_fetch + , coalesce(n_tup_ins,0)::float AS n_tup_ins + , coalesce(n_tup_upd,0)::float AS n_tup_upd + , coalesce(n_tup_del,0)::float AS n_tup_del + , coalesce(n_tup_hot_upd,0)::float AS n_tup_hot_upd + , coalesce(n_live_tup,0)::float AS n_live_tup + , coalesce(n_dead_tup,0)::float AS n_dead_tup + , coalesce(vacuum_count,0)::float AS vacuum_count + , coalesce(autovacuum_count,0)::float AS autovacuum_count + , coalesce(analyze_count,0)::float AS analyze_count + , coalesce(autoanalyze_count,0)::float AS autoanalyze_count + FROM pg_stat_user_tables FULL JOIN (VALUES(0)) filler(i) ON TRUE; + - name: "pg_statio_user_tables" + help: "IO Stats" + labels: + - "datname" + - "schemaname" + - "relname" + values: + - "heap_blks_read" + - "heap_blks_hit" + - "idx_blks_read" + - "idx_blks_hit" + query: | + SELECT + current_database()::text AS datname + , COALESCE(schemaname::text, 'null') AS schemaname + , COALESCE(relname::text, 'null') AS relname + , COALESCE(heap_blks_read::float,0) AS heap_blks_read + , COALESCE(heap_blks_hit::float,0) AS heap_blks_hit + , COALESCE(idx_blks_read::float,0) AS idx_blks_read + , COALESCE(idx_blks_hit::float,0) AS idx_blks_hit + FROM pg_statio_user_tables FULL JOIN (VALUES(0)) filler(i) ON TRUE; + - name: "BufferAccess" + help: "Buffers Accessed" + labels: + - "datname" + - "schemaname" + - "relname" + values: + - "reads" + query: | + SELECT + current_database()::text AS datname, + COALESCE(schemaname::text, 'null') AS schemaname, + COALESCE(relname::text, 'null') AS relname, + sum( coalesce( heap_blks_read,0) + + coalesce(heap_blks_hit,0) + + coalesce(idx_blks_hit,0) + + coalesce(idx_blks_read,0) + + coalesce(toast_blks_hit,0) + + coalesce(toast_blks_read,0) + + coalesce(tidx_blks_hit,0) + + coalesce(tidx_blks_read,0))*8196::bigint as reads + FROM pg_statio_user_tables FULL JOIN (VALUES(0)) filler(i) ON TRUE + GROUP BY 1,2,3; + - name: "Maintenancecounters" + help: "Counters for maintenance jobs on user tables" + labels: + - "datname" + values: + - "vacuum_count" + - "autovacuum_count" + - "analyze_count" + - "autoanalyze_count" + query: | + SELECT + current_database()::text AS datname, + sum( vacuum_count) vacuum_count, + sum( autovacuum_count) autovacuum_count, + sum( analyze_count) analyze_count, + sum( autoanalyze_count) autoanalyze_count + FROM pg_stat_all_tables; +<% if @extra_config -%> +<%= @extra_config.to_yaml().gsub(/^---\n/, '') %> +<%- end -%> diff --git a/site-modules/profile/templates/puppet/swh-puppet-apply.sh.erb b/site-modules/profile/templates/puppet/swh-puppet-apply.sh.erb new file mode 100644 index 00000000..16bb64ab --- /dev/null +++ b/site-modules/profile/templates/puppet/swh-puppet-apply.sh.erb @@ -0,0 +1,4 @@ +#!/bin/bash +# This file is managed by puppet. Local modifications will be overwritten. + +puppet agent --test diff --git a/site-modules/profile/templates/puppet/swh-puppet-master-deploy.sh.erb b/site-modules/profile/templates/puppet/swh-puppet-master-deploy.sh.erb new file mode 100644 index 00000000..46149c88 --- /dev/null +++ b/site-modules/profile/templates/puppet/swh-puppet-master-deploy.sh.erb @@ -0,0 +1,4 @@ +#!/bin/bash +# This file is managed by puppet. Local modifications will be overwritten. + +/etc/puppet/code/environments/production/deploy.sh -v diff --git a/site-modules/profile/templates/puppet/swh-puppet-test.sh.erb b/site-modules/profile/templates/puppet/swh-puppet-test.sh.erb new file mode 100644 index 00000000..569adca6 --- /dev/null +++ b/site-modules/profile/templates/puppet/swh-puppet-test.sh.erb @@ -0,0 +1,4 @@ +#!/bin/bash +# This file is managed by puppet. Local modifications will be overwritten. + +puppet agent --test --noop diff --git a/site-modules/profile/templates/swh/deploy/archiver/swh-archiver-content-updater.service.erb b/site-modules/profile/templates/swh/deploy/archiver/swh-archiver-content-updater.service.erb new file mode 100644 index 00000000..90c74fbe --- /dev/null +++ b/site-modules/profile/templates/swh/deploy/archiver/swh-archiver-content-updater.service.erb @@ -0,0 +1,19 @@ +# Journal Publisher unit file +# Managed by puppet class profile::swh::deploy::archiver_content_updater +# Changes will be overwritten + +[Unit] +Description=Software Heritage Archiver Content Updater +Requires=network.target kafka.service +After=network.target kafka.service + +[Service] +User=<%= @user %> +Group=<%= @group %> +Type=simple +ExecStart=/usr/bin/python3 -m swh.archiver.updater +Restart=always +RestartSec=5s + +[Install] +WantedBy=multi-user.target diff --git a/site-modules/profile/templates/swh/deploy/journal/swh-journal-publisher.service.erb b/site-modules/profile/templates/swh/deploy/journal/swh-journal-publisher.service.erb new file mode 100644 index 00000000..f7d72b3c --- /dev/null +++ b/site-modules/profile/templates/swh/deploy/journal/swh-journal-publisher.service.erb @@ -0,0 +1,19 @@ +# Journal Publisher unit file +# Managed by puppet class profile::swh::deploy::journal_publisher +# Changes will be overwritten + +[Unit] +Description=Software Heritage Journal Publisher +Requires=network.target kafka.service +After=network.target kafka.service + +[Service] +User=<%= @user %> +Group=<%= @group %> +Type=simple +ExecStart=/usr/bin/python3 -m swh.journal.publisher +Restart=always +RestartSec=5s + +[Install] +WantedBy=multi-user.target diff --git a/site-modules/profile/templates/swh/deploy/journal/swh-journal-simple-checker-producer.service.erb b/site-modules/profile/templates/swh/deploy/journal/swh-journal-simple-checker-producer.service.erb new file mode 100644 index 00000000..0a5212e1 --- /dev/null +++ b/site-modules/profile/templates/swh/deploy/journal/swh-journal-simple-checker-producer.service.erb @@ -0,0 +1,17 @@ +# Journal Checker unit file +# Managed by puppet class profile::swh::deploy::journal_simple_checker_producer +# Changes will be overwritten + +[Unit] +Description=Software Heritage Journal Checker +Requires=network.target kafka.service +After=network.target kafka.service + +[Service] +User=<%= @user %> +Group=<%= @group %> +Type=OneShot +ExecStart=/usr/bin/python3 -m swh.journal.checker + +[Install] +WantedBy=multi-user.target diff --git a/site-modules/profile/templates/swh/deploy/scheduler/scheduler.ini.erb b/site-modules/profile/templates/swh/deploy/scheduler/scheduler.ini.erb new file mode 100644 index 00000000..90af16e7 --- /dev/null +++ b/site-modules/profile/templates/swh/deploy/scheduler/scheduler.ini.erb @@ -0,0 +1,6 @@ +# swh.scheduler configuration file +# File managed by puppet - modifications will be overwritten + +[main] +scheduling_db = <%= @database %> + diff --git a/site-modules/profile/templates/swh/deploy/scheduler/ssh-ghtorrent.service.erb b/site-modules/profile/templates/swh/deploy/scheduler/ssh-ghtorrent.service.erb new file mode 100644 index 00000000..90e54818 --- /dev/null +++ b/site-modules/profile/templates/swh/deploy/scheduler/ssh-ghtorrent.service.erb @@ -0,0 +1,20 @@ +# SSH Ghtorrent unit file +# Managed by puppet class profile::swh::deploy::scheduler::updater::consumer +# Changes will be overwritten + +[Unit] +Description=SSH connection to GHTorrent infra +Requires=network-online.target +After=network-online.target + +[Service] +User=<%= @consumer_user %> +Group=<%= @consumer_group %> +Type=simple +Environment="AUTOSSH_GATETIME=0" +ExecStart=/usr/bin/autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -i <%= @ghtorrent_private_key %> -NL <%= @local_port %>:streamer.ghtorrent.org:5672 ghtorrent@streamer.ghtorrent.org +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target diff --git a/site-modules/profile/templates/swh/deploy/scheduler/swh-scheduler-listener.service.erb b/site-modules/profile/templates/swh/deploy/scheduler/swh-scheduler-listener.service.erb new file mode 100644 index 00000000..86b56d81 --- /dev/null +++ b/site-modules/profile/templates/swh/deploy/scheduler/swh-scheduler-listener.service.erb @@ -0,0 +1,19 @@ +# Scheduler Listener unit file +# Managed by puppet class profile::swh::deploy::scheduler +# Changes will be overwritten + +[Unit] +Description=Software Heritage scheduler listener +Requires=network.target rabbitmq-server.service +After=network.target rabbitmq-server.service + +[Service] +User=<%= @user %> +Group=<%= @group %> +Type=simple +ExecStart=/usr/bin/python3 -m swh.scheduler.celery_backend.listener +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target diff --git a/site-modules/profile/templates/swh/deploy/scheduler/swh-scheduler-runner.service.erb b/site-modules/profile/templates/swh/deploy/scheduler/swh-scheduler-runner.service.erb new file mode 100644 index 00000000..cc6ec84a --- /dev/null +++ b/site-modules/profile/templates/swh/deploy/scheduler/swh-scheduler-runner.service.erb @@ -0,0 +1,19 @@ +# Scheduler Runner unit file +# Managed by puppet class profile::swh::deploy::scheduler +# Changes will be overwritten + +[Unit] +Description=Software Heritage scheduler runner +Requires=network.target rabbitmq-server.service +After=network.target rabbitmq-server.service + +[Service] +User=<%= @user %> +Group=<%= @group %> +Type=simple +ExecStart=/bin/sh -c 'while true; do echo running pending tasks at `/bin/date`...; /usr/bin/python3 -m swh.scheduler.celery_backend.runner; sleep 10; done' +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target diff --git a/site-modules/profile/templates/swh/deploy/scheduler/swh-scheduler-updater-consumer-ghtorrent.service.erb b/site-modules/profile/templates/swh/deploy/scheduler/swh-scheduler-updater-consumer-ghtorrent.service.erb new file mode 100644 index 00000000..c1036e4e --- /dev/null +++ b/site-modules/profile/templates/swh/deploy/scheduler/swh-scheduler-updater-consumer-ghtorrent.service.erb @@ -0,0 +1,19 @@ +# Scheduler Updater Consumer unit file +# Managed by puppet class profile::swh::deploy::scheduler::updater::consumer +# Changes will be overwritten + +[Unit] +Description=Software Heritage Scheduler Updater Consumer +Requires=network.target ssh-ghtorrent.service +After=network.target ssh-ghtorrent.service + +[Service] +User=<%= @consumer_user %> +Group=<%= @consumer_group %> +Type=simple +ExecStart=/usr/bin/python3 -m swh.scheduler.updater.ghtorrent.cli +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target diff --git a/site-modules/profile/templates/swh/deploy/scheduler/swh-scheduler-updater-writer.service.erb b/site-modules/profile/templates/swh/deploy/scheduler/swh-scheduler-updater-writer.service.erb new file mode 100644 index 00000000..bf5569e1 --- /dev/null +++ b/site-modules/profile/templates/swh/deploy/scheduler/swh-scheduler-updater-writer.service.erb @@ -0,0 +1,17 @@ +# Scheduler Updater Writer unit file +# Managed by puppet class profile::swh::deploy::scheduler::updater::writer +# Changes will be overwritten + +[Unit] +Description=Software Heritage Scheduler Updater Writer +Requires=network.target +After=network.target + +[Service] +User=<%= @writer_user %> +Group=<%= @writer_group %> +Type=oneshot +ExecStart=/usr/bin/python3 -m swh.scheduler.updater.writer + +[Install] +WantedBy=multi-user.target diff --git a/site-modules/profile/templates/swh/deploy/scheduler/swh-scheduler-updater-writer.timer.erb b/site-modules/profile/templates/swh/deploy/scheduler/swh-scheduler-updater-writer.timer.erb new file mode 100644 index 00000000..debdd8fa --- /dev/null +++ b/site-modules/profile/templates/swh/deploy/scheduler/swh-scheduler-updater-writer.timer.erb @@ -0,0 +1,18 @@ +# Scheduler Updater Writer Timer unit file +# Managed by puppet class profile::swh::deploy::scheduler::updater::writer +# Changes will be overwritten + +[Unit] +Description=Software Heritage Scheduler Updater Writer Timer + +[Timer] +# Time to wait after booting before we run first time +OnBootSec=10min +# periodic run +OnCalendar=<%= @writer_timer_period %> +# of unit +Unit=<%= @writer_unit_name %> + +[Install] +WantedBy=timers.target + diff --git a/site-modules/profile/templates/swh/deploy/scheduler/worker.ini.erb b/site-modules/profile/templates/swh/deploy/scheduler/worker.ini.erb new file mode 100644 index 00000000..b358e30c --- /dev/null +++ b/site-modules/profile/templates/swh/deploy/scheduler/worker.ini.erb @@ -0,0 +1,7 @@ +# Managed by puppet - modifications will be overwritten +# In defined class profile::swh::deploy::scheduler + +[main] +task_broker = <%= @task_broker %> +task_modules = <%= @task_modules.join(', ') %> +task_queues = diff --git a/site-modules/profile/templates/swh/deploy/storage/objstorage_archive_notifier_checker.service.erb b/site-modules/profile/templates/swh/deploy/storage/objstorage_archive_notifier_checker.service.erb new file mode 100644 index 00000000..adc37572 --- /dev/null +++ b/site-modules/profile/templates/swh/deploy/storage/objstorage_archive_notifier_checker.service.erb @@ -0,0 +1,14 @@ +# File managed by puppet - modifications will be overwritten +[Unit] +Description=ObjStorage Archive Notifier Content Checker +After=network.target + +[Service] +User=<%= @user %> +Group=<%= @group %> +ExecStart=/usr/bin/python3 -m swh.objstorage.checker archiver_notifier --daemon +KillMode=process +Restart=on-failure + +[Install] +WantedBy=multi-user.target diff --git a/site-modules/profile/templates/swh/deploy/storage/objstorage_log_checker.service.erb b/site-modules/profile/templates/swh/deploy/storage/objstorage_log_checker.service.erb new file mode 100644 index 00000000..2483afe7 --- /dev/null +++ b/site-modules/profile/templates/swh/deploy/storage/objstorage_log_checker.service.erb @@ -0,0 +1,14 @@ +# File managed by puppet - modifications will be overwritten +[Unit] +Description=ObjStorage Content Log Checker +After=network.target + +[Service] +User=<%= @user %> +Group=<%= @group %> +ExecStart=/usr/bin/python3 -m swh.objstorage.checker log --daemon +KillMode=process +Restart=on-failure + +[Install] +WantedBy=multi-user.target diff --git a/site-modules/profile/templates/swh/deploy/storage/objstorage_repair_checker.service.erb b/site-modules/profile/templates/swh/deploy/storage/objstorage_repair_checker.service.erb new file mode 100644 index 00000000..da399771 --- /dev/null +++ b/site-modules/profile/templates/swh/deploy/storage/objstorage_repair_checker.service.erb @@ -0,0 +1,14 @@ +# File managed by puppet - modifications will be overwritten +[Unit] +Description=ObjStorage Repair Content Checker +After=network.target + +[Service] +User=<%= @user %> +Group=<%= @group %> +ExecStart=/usr/bin/python3 -m swh.objstorage.checker repair --daemon +KillMode=process +Restart=on-failure + +[Install] +WantedBy=multi-user.target diff --git a/site-modules/profile/templates/swh/deploy/storage/systemd-setrlimit.conf.erb b/site-modules/profile/templates/swh/deploy/storage/systemd-setrlimit.conf.erb new file mode 100644 index 00000000..0a7dd670 --- /dev/null +++ b/site-modules/profile/templates/swh/deploy/storage/systemd-setrlimit.conf.erb @@ -0,0 +1,2 @@ +[Service] +LimitNOFILE=65536 diff --git a/site-modules/profile/templates/swh/deploy/storage_listener/listener.ini.erb b/site-modules/profile/templates/swh/deploy/storage_listener/listener.ini.erb new file mode 100644 index 00000000..6ecc5158 --- /dev/null +++ b/site-modules/profile/templates/swh/deploy/storage_listener/listener.ini.erb @@ -0,0 +1,9 @@ +# swh.storage.listener configuration file +# File managed by puppet - modifications will be overwritten + +[main] +database = <%= @database %> +brokers = <%= @kafka_brokers.join(',') %> +topic_prefix = <%= @topic_prefix %> +poll_timeout = <%= @poll_timeout %> + diff --git a/site-modules/profile/templates/swh/deploy/storage_listener/swh-storage-listener.service.erb b/site-modules/profile/templates/swh/deploy/storage_listener/swh-storage-listener.service.erb new file mode 100644 index 00000000..5695fe62 --- /dev/null +++ b/site-modules/profile/templates/swh/deploy/storage_listener/swh-storage-listener.service.erb @@ -0,0 +1,19 @@ +# Storage Listener unit file +# Managed by puppet class profile::swh::deploy::storage_listener +# Changes will be overwritten + +[Unit] +Description=Software Heritage storage listener +Requires=network.target kafka.service +After=network.target kafka.service + +[Service] +User=<%= @user %> +Group=<%= @group %> +Type=simple +ExecStart=/usr/bin/python3 -m swh.storage.listener +Restart=always +RestartSec=5s + +[Install] +WantedBy=multi-user.target diff --git a/site-modules/profile/templates/swh/deploy/worker/instance_config.ini.erb b/site-modules/profile/templates/swh/deploy/worker/instance_config.ini.erb new file mode 100644 index 00000000..8539ab78 --- /dev/null +++ b/site-modules/profile/templates/swh/deploy/worker/instance_config.ini.erb @@ -0,0 +1,8 @@ +# Managed by puppet - modifications will be overwritten +# In defined class profile::swh::deploy::worker::instance + +[main] +task_broker = <%= @task_broker %> +task_modules = <%= @task_modules.join(', ') %> +task_queues = <%= @task_queues.join(', ') %> +task_soft_time_limit = <%= @task_soft_time_limit %> diff --git a/site-modules/profile/templates/swh/deploy/worker/parameters.conf.erb b/site-modules/profile/templates/swh/deploy/worker/parameters.conf.erb new file mode 100644 index 00000000..80487de1 --- /dev/null +++ b/site-modules/profile/templates/swh/deploy/worker/parameters.conf.erb @@ -0,0 +1,13 @@ +# Managed by puppet - modifications will be overwritten +# In defined class profile::swh::deploy::worker::instance + +[Service] +Environment=CONCURRENCY=<%= @concurrency %> +Environment=MAX_TASKS_PER_CHILD=<%= @max_tasks_per_child %> +Environment=LOGLEVEL=<%= @loglevel %> +<% if @limit_no_file %> +LimitNOFILE=<%= @limit_no_file %> +<% end %> +<% if @private_tmp %> +PrivateTmp=<%= @private_tmp %> +<% end %> diff --git a/site-modules/profile/templates/swh/logrotate.conf.erb b/site-modules/profile/templates/swh/logrotate.conf.erb new file mode 100644 index 00000000..70d1a232 --- /dev/null +++ b/site-modules/profile/templates/swh/logrotate.conf.erb @@ -0,0 +1,10 @@ +# Software Heritage logrotate configuration +# Managed by puppet. Changes will be overwritten. + +<%= @swh_log_directory %>/*.log { + weekly + missingok + rotate 5 + compress + notifempty +} diff --git a/site-modules/profile/templates/systemd_journal/journalbeat/journalbeat.service.erb b/site-modules/profile/templates/systemd_journal/journalbeat/journalbeat.service.erb new file mode 100644 index 00000000..c9db293f --- /dev/null +++ b/site-modules/profile/templates/systemd_journal/journalbeat/journalbeat.service.erb @@ -0,0 +1,19 @@ +# Managed by puppet (class profile::systemd_journal::journalbeat), changes will be lost + +[Unit] +Description=Send systemd journal messages to logstash +After=nss-lookup.target + +[Service] +Type=simple +Restart=always +RestartSec=20s +ExecStart=/usr/bin/journalbeat -e -c <%= @configfile %> +User=<%= @user %> +Group=systemd-journal +ReadOnlyDirectories=/ +ReadWriteDirectories=-<%= @homedir %> +WorkingDirectory=<%= @homedir %> + +[Install] +WantedBy=multi-user.target diff --git a/site-modules/profile/templates/systemd_journal/journalbeat/journalbeat.yml.erb b/site-modules/profile/templates/systemd_journal/journalbeat/journalbeat.yml.erb new file mode 100644 index 00000000..c82584b2 --- /dev/null +++ b/site-modules/profile/templates/systemd_journal/journalbeat/journalbeat.yml.erb @@ -0,0 +1,305 @@ +#======================== Journalbeat Configuration ============================ + +journalbeat: + # What position in journald to seek to at start up + # options: cursor, tail, head (defaults to tail) + seek_position: cursor + + # If seek_position is set to cursor and seeking to cursor fails + # fall back to this method. If set to none will it will exit + # options: tail, head, none (defaults to tail) + cursor_seek_fallback: head + + # Store the cursor of the successfully published events + write_cursor_state: true + + # Path to the file to store the cursor (defaults to ".journalbeat-cursor-state") + cursor_state_file: cursor-state + + # How frequently should we save the cursor to disk (defaults to 5s) + #cursor_flush_period: 5s + + # Path to the file to store the queue of events pending (defaults to ".journalbeat-pending-queue") + pending_queue.file: pending-queue + + # How frequently should we save the queue to disk (defaults to 1s). + # Pending queue represents the WAL of events queued to be published + # or being published and waiting for acknowledgement. In case of a + # regular restart of journalbeat all the events not yet acknowledged + # will be flushed to disk during the shutdown. + # In case of disaster most probably journalbeat won't get a chance to shutdown + # itself gracefully and this flush period option will serve you as a + # backup creation frequency option. + pending_queue.flush_period: 1s + + # Lowercase and remove leading underscores, e.g. "_MESSAGE" -> "message" + # (default to false) + clean_field_names: true + + # All journal entries are strings by default. You can try to convert them to numbers. + # (defaults to false) + convert_to_numbers: false + + # Store all the fields of the Systemd Journal entry under this field + # Can be almost any string suitable to be a field name of an ElasticSearch document. + # Dots can be used to create nested fields. + # Two exceptions: + # - no repeated dots; + # - no trailing dots, e.g. "journal..field_name." will fail + # (defaults to "" hence stores on the upper level of the event) + #move_metadata_to_field: "" + + # Specific units to monitor. + #units: ["httpd.service"] + + # Directory to monitor instead of connecting to the default journal location + #directory: /var/log/journal/remote + + #default_type: journal + +#================================ General ====================================== + +# The name of the shipper that publishes the network data. It can be used to group +# all the transactions sent by a single shipper in the web interface. +# If this options is not defined, the hostname is used. +#name: journalbeat + +# The tags of the shipper are included in their own field with each +# transaction published. Tags make it easy to group servers by different +# logical properties. +#tags: ["service-X", "web-tier"] + +# Optional fields that you can specify to add additional information to the +# output. Fields can be scalar values, arrays, dictionaries, or any nested +# combination of these. +#fields: +# env: staging + +# If this option is set to true, the custom fields are stored as top-level +# fields in the output document instead of being grouped under a fields +# sub-dictionary. Default is false. +#fields_under_root: false + +# Internal queue size for single events in processing pipeline +#queue_size: 1000 + +# The internal queue size for bulk events in the processing pipeline. +# Do not modify this value. +#bulk_queue_size: 0 + +# Sets the maximum number of CPUs that can be executing simultaneously. The +# default is the number of logical CPUs available in the system. +#max_procs: + +#================================ Processors =================================== + +# Processors are used to reduce the number of fields in the exported event or to +# enhance the event with external metadata. This section defines a list of +# processors that are applied one by one and the first one receives the initial +# event: +# +# event -> filter1 -> event1 -> filter2 ->event2 ... +# +# The supported processors are drop_fields, drop_event, include_fields, and +# add_cloud_metadata. +# +# For example, you can use the following processors to keep the fields that +# contain CPU load percentages, but remove the fields that contain CPU ticks +# values: +# +#processors: +#- include_fields: +# fields: ["cpu"] +#- drop_fields: +# fields: ["cpu.user", "cpu.system"] +# +# The following example drops the events that have the HTTP response code 200: +# +#processors: +#- drop_event: +# when: +# equals: +# http.code: 200 +# +# The following example enriches each event with metadata from the cloud +# provider about the host machine. It works on EC2, GCE, and DigitalOcean. +# +#processors: +#- add_cloud_metadata: +# + +#================================ Outputs ====================================== + +# Configure what outputs to use when sending the data collected by the beat. +# Multiple outputs may be used. + +output.elasticsearch: + enabled: false + +#----------------------------- Logstash output --------------------------------- +output.logstash: + # Boolean flag to enable or disable the output module. + enabled: true + + # The Logstash hosts + hosts: +<% @logstash_hosts.each do |host| -%> + - <%= host %> +<% end -%> + + # Number of workers per Logstash host. + #worker: 1 + + # Set gzip compression level. + #compression_level: 3 + + # Optional load balance the events between the Logstash hosts + #loadbalance: true + + # Number of batches to be send asynchronously to logstash while processing + # new batches. + #pipelining: 0 + + # Optional index name. The default index name is set to name of the beat + # in all lowercase. + #index: 'beatname' + + # SOCKS5 proxy server URL + #proxy_url: socks5://user:password@socks5-server:2233 + + # Resolve names locally when using a proxy server. Defaults to false. + #proxy_use_local_resolver: false + + # Enable SSL support. SSL is automatically enabled, if any SSL setting is set. + #ssl.enabled: true + + # Configure SSL verification mode. If `none` is configured, all server hosts + # and certificates will be accepted. In this mode, SSL based connections are + # susceptible to man-in-the-middle attacks. Use only for testing. Default is + # `full`. + #ssl.verification_mode: full + + # List of supported/valid TLS versions. By default all TLS versions 1.0 up to + # 1.2 are enabled. + #ssl.supported_protocols: [TLSv1.0, TLSv1.1, TLSv1.2] + + # Optional SSL configuration options. SSL is off by default. + # List of root certificates for HTTPS server verifications + #ssl.certificate_authorities: ["/etc/pki/root/ca.pem"] + + # Certificate for SSL client authentication + #ssl.certificate: "/etc/pki/client/cert.pem" + + # Client Certificate Key + #ssl.key: "/etc/pki/client/cert.key" + + # Optional passphrase for decrypting the Certificate Key. + #ssl.key_passphrase: '' + + # Configure cipher suites to be used for SSL connections + #ssl.cipher_suites: [] + + # Configure curve types for ECDHE based cipher suites + #ssl.curve_types: [] + +#------------------------------- File output ----------------------------------- +#output.file: + # Boolean flag to enable or disable the output module. + #enabled: true + + # Path to the directory where to save the generated files. The option is + # mandatory. + #path: "/tmp/beatname" + + # Name of the generated files. The default is `beatname` and it generates + # files: `beatname`, `beatname.1`, `beatname.2`, etc. + #filename: beatname + + # Maximum size in kilobytes of each file. When this size is reached, and on + # every beatname restart, the files are rotated. The default value is 10240 + # kB. + #rotate_every_kb: 10000 + + # Maximum number of files under path. When this number of files is reached, + # the oldest file is deleted and the rest are shifted from last to first. The + # default is 7 files. + #number_of_files: 7 + + +#----------------------------- Console output --------------------------------- +#output.console: + # Boolean flag to enable or disable the output module. + #enabled: true + + # Pretty print json event + #pretty: true + +#================================= Paths ====================================== + +# The home path for the beatname installation. This is the default base path +# for all other path settings and for miscellaneous files that come with the +# distribution (for example, the sample dashboards). +# If not set by a CLI flag or in the configuration file, the default for the +# home path is the location of the binary. +path.home: <%= @homedir %> + +# The configuration path for the beatname installation. This is the default +# base path for configuration files, including the main YAML configuration file +# and the Elasticsearch template file. If not set by a CLI flag or in the +# configuration file, the default for the configuration path is the home path. +#path.config: ${path.home} + +# The data path for the beatname installation. This is the default base path +# for all the files in which beatname needs to store its data. If not set by a +# CLI flag or in the configuration file, the default for the data path is a data +# subdirectory inside the home path. +#path.data: ${path.home}/data + +# The logs path for a beatname installation. This is the default location for +# the Beat's log files. If not set by a CLI flag or in the configuration file, +# the default for the logs path is a logs subdirectory inside the home path. +#path.logs: ${path.home}/logs + +#================================ Logging ====================================== +# There are three options for the log output: syslog, file, stderr. +# Under Windows systems, the log files are per default sent to the file output, +# under all other system per default to syslog. + +# Sets log level. The default log level is info. +# Available log levels are: critical, error, warning, info, debug +logging.level: info + +# Enable debug output for selected components. To enable all selectors use ["*"] +# Other available selectors are "beat", "publish", "service" +# Multiple selectors can be chained. +logging.selectors: ["*"] + +# Send all logging output to syslog. The default is false. +logging.to_syslog: true + +# If enabled, beatname periodically logs its internal metrics that have changed +# in the last period. For each metric that changed, the delta from the value at +# the beginning of the period is logged. Also, the total values for +# all non-zero internal metrics are logged on shutdown. The default is true. +logging.metrics.enabled: false + +# The period after which to log the internal metrics. The default is 30s. +logging.metrics.period: 30s + +# Logging to rotating files files. Set logging.to_files to false to disable logging to +# files. +logging.to_files: false +logging.files: + # Configure the path where the logs are written. The default is the logs directory + # under the home path (the binary location). + #path: /var/log/beatname + + # The name of the files where the logs are written to. + #name: beatname + + # Configure log file size limit. If limit is reached, log file will be + # automatically rotated + #rotateeverybytes: 10485760 # = 10MB + + # Number of rotated log files to keep. Oldest files will be deleted first. + #keepfiles: 7 diff --git a/site-modules/profile/templates/unbound/forwarders.conf.erb b/site-modules/profile/templates/unbound/forwarders.conf.erb new file mode 100644 index 00000000..206c5761 --- /dev/null +++ b/site-modules/profile/templates/unbound/forwarders.conf.erb @@ -0,0 +1,15 @@ +# File managed by puppet (class profile::unbound), all changes will be lost + +forward-zone: + name: "." +<% @forwarders.each do |forwarder| -%> + forward-addr: <%= forwarder %> +<% end -%> + +<% @forward_zones.each do |zone, forwarders| -%> +forward-zone: + name: "<%= zone %>" +<% forwarders.each do |forwarder| -%> + forward-addr: <%= forwarder %> +<% end -%> +<% end -%> diff --git a/site-modules/profile/templates/varnish/backend_default.vcl.erb b/site-modules/profile/templates/varnish/backend_default.vcl.erb new file mode 100644 index 00000000..787d00df --- /dev/null +++ b/site-modules/profile/templates/varnish/backend_default.vcl.erb @@ -0,0 +1,10 @@ +# backend_default.vcl +# +# Default backend definition. +# +# File managed by puppet. All modifications will be lost. + +backend default { + .host = "::1"; + .port = "<%= scope['::profile::varnish::backend_http_port'] %>"; +} diff --git a/site-modules/profile/templates/varnish/default.vcl.erb b/site-modules/profile/templates/varnish/default.vcl.erb new file mode 100644 index 00000000..4d8aad62 --- /dev/null +++ b/site-modules/profile/templates/varnish/default.vcl.erb @@ -0,0 +1,9 @@ +# Varnish configuration file +# File managed by puppet (module profile::varnish) +# All modifications will be lost. + +vcl 4.0; + +import std; + +include "<%= @includes_vcl_name %>"; diff --git a/site-modules/profile/templates/varnish/vhost.vcl.erb b/site-modules/profile/templates/varnish/vhost.vcl.erb new file mode 100644 index 00000000..0cb7b7af --- /dev/null +++ b/site-modules/profile/templates/varnish/vhost.vcl.erb @@ -0,0 +1,44 @@ +# vhost_<%= @servername %>.vcl +# +# Settings for the <%= @servername %> vhost +# +# File managed by puppet. All modifications will be lost. + +sub vcl_recv { + if ( +<% @aliases.each do |alias_| -%> + req.http.host ~ "^(?i)<%= Regexp.escape(alias_) %>$" || +<% end -%> + req.http.host ~ "^(?i)<%= Regexp.escape(@servername) %>$" + ) { + if (std.port(server.ip) == <%= scope['::profile::varnish::http_port'] %>) { + set req.http.x-redir = "https://" + req.http.host + req.url; + return(synth(850, "Moved permanently")); + } else { + set req.http.X_FORWARDED_PROTO = "https"; + } +<% if @vcl_recv_extra -%> + <%= @vcl_recv_extra %> +<% end -%> + } +} + +<% if @hsts_max_age or @vcl_deliver_extra -%> +sub vcl_deliver { + if ( +<% @aliases.each do |alias_| -%> + req.http.host ~ "^(?i)<%= Regexp.escape(alias_) %>$" || +<% end -%> + req.http.host ~ "^(?i)<%= Regexp.escape(@servername) %>$" + ) { +<% if @hsts_max_age -%> + if (std.port(server.ip) != <%= scope['::profile::varnish::http_port'] %>) { + set resp.http.Strict-Transport-Security = "max-age=<%= @hsts_max_age %>;"; + } +<% end -%> +<% if @vcl_deliver_extra -%> + <%= @vcl_deliver_extra %> +<% end -%> + } +} +<% end -%> diff --git a/site-modules/profile/tests/init.pp b/site-modules/profile/tests/init.pp new file mode 100644 index 00000000..a50248e0 --- /dev/null +++ b/site-modules/profile/tests/init.pp @@ -0,0 +1,12 @@ +# The baseline for module testing used by Puppet Labs is that each manifest +# should have a corresponding test manifest that declares that class or defined +# type. +# +# Tests are then run by using puppet apply --noop (to check for compilation +# errors and view a log of events) or by fully applying the test in a virtual +# environment (to compare the resulting system state to the desired state). +# +# Learn more about module testing here: +# http://docs.puppetlabs.com/guides/tests_smoke.html +# +include profile diff --git a/site-modules/role/AUTHORS b/site-modules/role/AUTHORS new file mode 100644 index 00000000..2d0a34af --- /dev/null +++ b/site-modules/role/AUTHORS @@ -0,0 +1,3 @@ +Copyright (C) 2015 The Software Heritage developers + +See http://www.softwareheritage.org/ for more information. diff --git a/site-modules/role/Gemfile b/site-modules/role/Gemfile new file mode 100644 index 00000000..7bd34cda --- /dev/null +++ b/site-modules/role/Gemfile @@ -0,0 +1,7 @@ +source 'https://rubygems.org' + +puppetversion = ENV.key?('PUPPET_VERSION') ? "= #{ENV['PUPPET_VERSION']}" : ['>= 3.3'] +gem 'puppet', puppetversion +gem 'puppetlabs_spec_helper', '>= 0.1.0' +gem 'puppet-lint', '>= 0.3.2' +gem 'facter', '>= 1.7.0' diff --git a/site-modules/role/LICENSE b/site-modules/role/LICENSE new file mode 100644 index 00000000..37ec93a1 --- /dev/null +++ b/site-modules/role/LICENSE @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/site-modules/role/README.md b/site-modules/role/README.md new file mode 100644 index 00000000..a9a9a8cc --- /dev/null +++ b/site-modules/role/README.md @@ -0,0 +1,79 @@ +# role + +#### Table of Contents + +1. [Overview](#overview) +2. [Module Description - What the module does and why it is useful](#module-description) +3. [Setup - The basics of getting started with role](#setup) + * [What role affects](#what-role-affects) + * [Setup requirements](#setup-requirements) + * [Beginning with role](#beginning-with-role) +4. [Usage - Configuration options and additional functionality](#usage) +5. [Reference - An under-the-hood peek at what the module is doing and how](#reference) +5. [Limitations - OS compatibility, etc.](#limitations) +6. [Development - Guide for contributing to the module](#development) + +## Overview + +A one-maybe-two sentence summary of what the module does/what problem it solves. +This is your 30 second elevator pitch for your module. Consider including +OS/Puppet version it works with. + +## Module Description + +If applicable, this section should have a brief description of the technology +the module integrates with and what that integration enables. This section +should answer the questions: "What does this module *do*?" and "Why would I use +it?" + +If your module has a range of functionality (installation, configuration, +management, etc.) this is the time to mention it. + +## Setup + +### What role affects + +* A list of files, packages, services, or operations that the module will alter, + impact, or execute on the system it's installed on. +* This is a great place to stick any warnings. +* Can be in list or paragraph form. + +### Setup Requirements **OPTIONAL** + +If your module requires anything extra before setting up (pluginsync enabled, +etc.), mention it here. + +### Beginning with role + +The very basic steps needed for a user to get the module up and running. + +If your most recent release breaks compatibility or requires particular steps +for upgrading, you may wish to include an additional section here: Upgrading +(For an example, see http://forge.puppetlabs.com/puppetlabs/firewall). + +## Usage + +Put the classes, types, and resources for customizing, configuring, and doing +the fancy stuff with your module here. + +## Reference + +Here, list the classes, types, providers, facts, etc contained in your module. +This section should include all of the under-the-hood workings of your module so +people know what the module is touching on their system but don't need to mess +with things. (We are working on automating this section!) + +## Limitations + +This is where you list OS compatibility, version compatibility, etc. + +## Development + +Since your module is awesome, other users will want to play with it. Let them +know what the ground rules for contributing are. + +## Release Notes/Contributors/Etc **Optional** + +If you aren't using changelog, put your release notes here (though you should +consider using changelog). You may also add any additional sections you feel are +necessary or important to include here. Please use the `## ` header. diff --git a/site-modules/role/Rakefile b/site-modules/role/Rakefile new file mode 100644 index 00000000..bb8e81fa --- /dev/null +++ b/site-modules/role/Rakefile @@ -0,0 +1,21 @@ +require 'rubygems' +require 'puppetlabs_spec_helper/rake_tasks' +require 'puppet-lint/tasks/puppet-lint' +PuppetLint.configuration.send('disable_80chars') +PuppetLint.configuration.send('disable_autoloader_layout') +PuppetLint.configuration.send('disable_variable_scope') +PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"] + +desc "Validate manifests, templates, and ruby files" +task :validate do + parser_flag = Puppet.version.start_with?('3.') ? '--parser=future' : '' + Dir['manifests/**/*.pp'].each do |manifest| + sh "puppet parser validate #{parser_flag} --noop #{manifest}" + end + Dir['spec/**/*.rb','lib/**/*.rb'].each do |ruby_file| + sh "ruby -c #{ruby_file}" unless ruby_file =~ /spec\/fixtures/ + end + Dir['templates/**/*.erb'].each do |template| + sh "erb -P -x -T '-' #{template} | ruby -c" + end +end diff --git a/site-modules/role/manifests/swh_api.pp b/site-modules/role/manifests/swh_api.pp new file mode 100644 index 00000000..d7918202 --- /dev/null +++ b/site-modules/role/manifests/swh_api.pp @@ -0,0 +1,11 @@ +class role::swh_api inherits role::swh_server { + include profile::network + include profile::puppet::agent + + # Web UI + include profile::memcached + include profile::swh::deploy::storage + include profile::swh::deploy::indexer_storage + include profile::swh::deploy::webapp + include profile::swh::deploy::deposit +} diff --git a/site-modules/role/manifests/swh_api_azure.pp b/site-modules/role/manifests/swh_api_azure.pp new file mode 100644 index 00000000..02259a42 --- /dev/null +++ b/site-modules/role/manifests/swh_api_azure.pp @@ -0,0 +1,13 @@ +# expansion of role::swh_api +# -network: incompatible with Azure infrastructure +# -deposit: not need for it + +class role::swh_api_azure inherits role::swh_server { + include profile::puppet::agent + + # Web UI + include profile::memcached + include profile::swh::deploy::storage + include profile::swh::deploy::indexer_storage + include profile::swh::deploy::webapp +} diff --git a/site-modules/role/manifests/swh_backup.pp b/site-modules/role/manifests/swh_backup.pp new file mode 100644 index 00000000..5dd7aa65 --- /dev/null +++ b/site-modules/role/manifests/swh_backup.pp @@ -0,0 +1,4 @@ +class role::swh_backup inherits role::swh_server { + include profile::puppet::agent + include profile::swh::deploy::objstorage +} diff --git a/site-modules/role/manifests/swh_base.pp b/site-modules/role/manifests/swh_base.pp new file mode 100644 index 00000000..9f0a1dbe --- /dev/null +++ b/site-modules/role/manifests/swh_base.pp @@ -0,0 +1,13 @@ +class role::swh_base { + include profile::base + include profile::ssh::server + include profile::unbound + include profile::systemd_journal + include profile::resolv_conf + include profile::munin::node + include profile::icinga2 + include profile::rsyslog + + + include profile::swh +} diff --git a/site-modules/role/manifests/swh_ceph.pp b/site-modules/role/manifests/swh_ceph.pp new file mode 100644 index 00000000..e0728e13 --- /dev/null +++ b/site-modules/role/manifests/swh_ceph.pp @@ -0,0 +1,4 @@ +class role::swh_ceph inherits role::swh_base { + include profile::puppet::agent + include profile::prometheus::node +} diff --git a/site-modules/role/manifests/swh_ceph_mon.pp b/site-modules/role/manifests/swh_ceph_mon.pp new file mode 100644 index 00000000..2c5f5887 --- /dev/null +++ b/site-modules/role/manifests/swh_ceph_mon.pp @@ -0,0 +1,3 @@ +class role::swh_ceph_mon inherits role::swh_ceph { + include profile::ceph::mon +} diff --git a/site-modules/role/manifests/swh_ceph_osd.pp b/site-modules/role/manifests/swh_ceph_osd.pp new file mode 100644 index 00000000..45f9d627 --- /dev/null +++ b/site-modules/role/manifests/swh_ceph_osd.pp @@ -0,0 +1,3 @@ +class role::swh_ceph_osd inherits role::swh_ceph { + include profile::ceph::osd +} diff --git a/site-modules/role/manifests/swh_ci.pp b/site-modules/role/manifests/swh_ci.pp new file mode 100644 index 00000000..79702fa5 --- /dev/null +++ b/site-modules/role/manifests/swh_ci.pp @@ -0,0 +1,5 @@ +# doesn't inherit swh_server to avoid backups by default +class role::swh_ci inherits role::swh_base { + include profile::puppet::agent + include profile::prometheus::node +} diff --git a/site-modules/role/manifests/swh_ci_server.pp b/site-modules/role/manifests/swh_ci_server.pp new file mode 100644 index 00000000..947002c9 --- /dev/null +++ b/site-modules/role/manifests/swh_ci_server.pp @@ -0,0 +1,9 @@ +class role::swh_ci_server inherits role::swh_ci { + # Restore backups for ci server + include profile::dar::client + + include profile::jenkins::server + + # single node setup for now + include profile::jenkins::worker +} diff --git a/site-modules/role/manifests/swh_database.pp b/site-modules/role/manifests/swh_database.pp new file mode 100644 index 00000000..7cc2079f --- /dev/null +++ b/site-modules/role/manifests/swh_database.pp @@ -0,0 +1,9 @@ +class role::swh_database inherits role::swh_server { + include profile::puppet::agent + + include profile::prometheus::node + include profile::prometheus::sql + + include profile::munin::plugins::postgresql + include profile::postgresql +} diff --git a/site-modules/role/manifests/swh_desktop.pp b/site-modules/role/manifests/swh_desktop.pp new file mode 100644 index 00000000..610a8d2b --- /dev/null +++ b/site-modules/role/manifests/swh_desktop.pp @@ -0,0 +1,6 @@ +class role::swh_desktop inherits role::swh_base { + include profile::puppet::agent + include profile::desktop + include profile::devel + include profile::postgresql +} diff --git a/site-modules/role/manifests/swh_elasticsearch.pp b/site-modules/role/manifests/swh_elasticsearch.pp new file mode 100644 index 00000000..5eea8645 --- /dev/null +++ b/site-modules/role/manifests/swh_elasticsearch.pp @@ -0,0 +1,4 @@ +class role::swh_elasticsearch inherits role::swh_base { + include profile::puppet::agent + include profile::elasticsearch +} diff --git a/site-modules/role/manifests/swh_eventlog.pp b/site-modules/role/manifests/swh_eventlog.pp new file mode 100644 index 00000000..86a94b9c --- /dev/null +++ b/site-modules/role/manifests/swh_eventlog.pp @@ -0,0 +1,6 @@ +class role::swh_eventlog inherits role::swh_server { + include profile::puppet::agent + + include profile::kafka::broker + include profile::swh::deploy::storage_listener +} diff --git a/site-modules/role/manifests/swh_forge.pp b/site-modules/role/manifests/swh_forge.pp new file mode 100644 index 00000000..db3433cc --- /dev/null +++ b/site-modules/role/manifests/swh_forge.pp @@ -0,0 +1,9 @@ +class role::swh_forge inherits role::swh_server { + include profile::network + include profile::puppet::agent + + include profile::apache::rewrite_domains + + include profile::phabricator + include profile::mediawiki +} diff --git a/site-modules/role/manifests/swh_hypervisor.pp b/site-modules/role/manifests/swh_hypervisor.pp new file mode 100644 index 00000000..372698b0 --- /dev/null +++ b/site-modules/role/manifests/swh_hypervisor.pp @@ -0,0 +1,3 @@ +class role::swh_hypervisor inherits role::swh_server { + include profile::puppet::agent +} diff --git a/site-modules/role/manifests/swh_hypervisor_master.pp b/site-modules/role/manifests/swh_hypervisor_master.pp new file mode 100644 index 00000000..37278c08 --- /dev/null +++ b/site-modules/role/manifests/swh_hypervisor_master.pp @@ -0,0 +1,3 @@ +class role::swh_hypervisor_master inherits role::swh_hypervisor { + include profile::dar::server +} diff --git a/site-modules/role/manifests/swh_remote_objstorage.pp b/site-modules/role/manifests/swh_remote_objstorage.pp new file mode 100644 index 00000000..37374829 --- /dev/null +++ b/site-modules/role/manifests/swh_remote_objstorage.pp @@ -0,0 +1,4 @@ +class role::swh_remote_objstorage inherits role::swh_base { + include profile::puppet::agent + include profile::swh::deploy::objstorage +} diff --git a/site-modules/role/manifests/swh_scheduler.pp b/site-modules/role/manifests/swh_scheduler.pp new file mode 100644 index 00000000..7b19f46b --- /dev/null +++ b/site-modules/role/manifests/swh_scheduler.pp @@ -0,0 +1,9 @@ +class role::swh_scheduler inherits role::swh_server { + include profile::puppet::agent + + # Scheduler + include profile::rabbitmq + include profile::swh::deploy::scheduler + include profile::swh::deploy::scheduler_updater_consumer + include profile::swh::deploy::scheduler_updater_writer +} diff --git a/site-modules/role/manifests/swh_server.pp b/site-modules/role/manifests/swh_server.pp new file mode 100644 index 00000000..a92c3bb8 --- /dev/null +++ b/site-modules/role/manifests/swh_server.pp @@ -0,0 +1,3 @@ +class role::swh_server inherits role::swh_base { + include profile::dar::client +} diff --git a/site-modules/role/manifests/swh_storage.pp b/site-modules/role/manifests/swh_storage.pp new file mode 100644 index 00000000..5d289b7d --- /dev/null +++ b/site-modules/role/manifests/swh_storage.pp @@ -0,0 +1,7 @@ +class role::swh_storage inherits role::swh_server { + include profile::puppet::agent + include profile::swh::deploy::storage + include profile::swh::deploy::indexer_storage + include profile::swh::deploy::objstorage + include profile::swh::deploy::worker +} diff --git a/site-modules/role/manifests/swh_sysadmin.pp b/site-modules/role/manifests/swh_sysadmin.pp new file mode 100644 index 00000000..9d5c8fd4 --- /dev/null +++ b/site-modules/role/manifests/swh_sysadmin.pp @@ -0,0 +1,24 @@ +class role::swh_sysadmin inherits role::swh_server { + include profile::network + + include profile::munin::master + include profile::munin::stats_export + + include profile::prometheus::server + include profile::grafana + + include profile::prometheus::node + include profile::prometheus::sql + + include profile::puppet::master + + include profile::icinga2::icingaweb2 + + include profile::apache::simple_server + include profile::bind_server + include profile::munin::plugins::postgresql + + include profile::annex_web + include profile::docs_web + include profile::debian_repository +} diff --git a/site-modules/role/manifests/swh_vault.pp b/site-modules/role/manifests/swh_vault.pp new file mode 100644 index 00000000..811152d9 --- /dev/null +++ b/site-modules/role/manifests/swh_vault.pp @@ -0,0 +1,9 @@ +class role::swh_vault inherits role::swh_server { + include profile::puppet::agent + include profile::swh::deploy::vault + + include profile::munin::plugins::postgresql + include profile::postgresql + + include profile::swh::deploy::objstorage +} diff --git a/site-modules/role/manifests/swh_vault_test.pp b/site-modules/role/manifests/swh_vault_test.pp new file mode 100644 index 00000000..6c7e188c --- /dev/null +++ b/site-modules/role/manifests/swh_vault_test.pp @@ -0,0 +1,11 @@ +class role::swh_vault_test inherits role::swh_server { + include profile::puppet::agent + + include profile::swh::deploy::vault + include profile::swh::deploy::worker + + include profile::munin::plugins::postgresql + include profile::postgresql + + include profile::swh::deploy::objstorage +} diff --git a/site-modules/role/manifests/swh_worker.pp b/site-modules/role/manifests/swh_worker.pp new file mode 100644 index 00000000..5f440993 --- /dev/null +++ b/site-modules/role/manifests/swh_worker.pp @@ -0,0 +1,5 @@ +class role::swh_worker inherits role::swh_base { + include profile::puppet::agent + include profile::swh::deploy::worker + include profile::mountpoints +} diff --git a/site-modules/role/manifests/swh_worker_azure.pp b/site-modules/role/manifests/swh_worker_azure.pp new file mode 100644 index 00000000..8ef16342 --- /dev/null +++ b/site-modules/role/manifests/swh_worker_azure.pp @@ -0,0 +1,5 @@ +# Configuration for Azure workers + +class role::swh_worker_azure inherits role::swh_worker { + +} diff --git a/site-modules/role/manifests/swh_worker_inria.pp b/site-modules/role/manifests/swh_worker_inria.pp new file mode 100644 index 00000000..0200d7b3 --- /dev/null +++ b/site-modules/role/manifests/swh_worker_inria.pp @@ -0,0 +1,3 @@ +class role::swh_worker_inria inherits role::swh_worker { + include profile::network +} diff --git a/site-modules/role/manifests/swh_worker_inria_miracle.pp b/site-modules/role/manifests/swh_worker_inria_miracle.pp new file mode 100644 index 00000000..9a7462b0 --- /dev/null +++ b/site-modules/role/manifests/swh_worker_inria_miracle.pp @@ -0,0 +1,4 @@ +class role::swh_worker_inria_miracle inherits role::swh_worker_inria { + # Add backups for /home + include profile::dar::client +} diff --git a/site-modules/role/metadata.json b/site-modules/role/metadata.json new file mode 100644 index 00000000..5dd7f407 --- /dev/null +++ b/site-modules/role/metadata.json @@ -0,0 +1,14 @@ +{ + "name": "swh-role", + "version": "0.1.0", + "author": "swh", + "summary": "Software Heritage Puppet Roles", + "license": "Apache 2.0", + "source": "git@git.softwareheritage.org:swh/sysadm/puppet/swh-role", + "project_page": null, + "issues_url": null, + "dependencies": [ + {"name":"puppetlabs-stdlib","version_requirement":">= 1.0.0"} + ] +} + diff --git a/site-modules/role/spec/classes/init_spec.rb b/site-modules/role/spec/classes/init_spec.rb new file mode 100644 index 00000000..69bfec5a --- /dev/null +++ b/site-modules/role/spec/classes/init_spec.rb @@ -0,0 +1,7 @@ +require 'spec_helper' +describe 'role' do + + context 'with defaults for all parameters' do + it { should contain_class('role') } + end +end diff --git a/site-modules/role/spec/spec_helper.rb b/site-modules/role/spec/spec_helper.rb new file mode 100644 index 00000000..2c6f5664 --- /dev/null +++ b/site-modules/role/spec/spec_helper.rb @@ -0,0 +1 @@ +require 'puppetlabs_spec_helper/module_spec_helper' diff --git a/site-modules/role/tests/init.pp b/site-modules/role/tests/init.pp new file mode 100644 index 00000000..caee90e0 --- /dev/null +++ b/site-modules/role/tests/init.pp @@ -0,0 +1,12 @@ +# The baseline for module testing used by Puppet Labs is that each manifest +# should have a corresponding test manifest that declares that class or defined +# type. +# +# Tests are then run by using puppet apply --noop (to check for compilation +# errors and view a log of events) or by fully applying the test in a virtual +# environment (to compare the resulting system state to the desired state). +# +# Learn more about module testing here: +# http://docs.puppetlabs.com/guides/tests_smoke.html +# +include role