├── .clj-kondo ├── config.edn └── hooks.clj ├── .dir-locals.el ├── .dockerignore ├── .gitattributes ├── .github └── workflows │ ├── daily.yml │ ├── docs_publish.yml │ ├── docs_test.yml │ ├── jira.yml │ ├── main.yml │ └── mend.yaml ├── .gitignore ├── .mailmap ├── CODEOWNERS ├── Gemfile ├── LICENSE.txt ├── Makefile ├── NOTICE.txt ├── README.md ├── Rakefile ├── acceptance ├── README.md ├── config │ ├── ec2-west-el7-64mda-el7-64a.cfg │ ├── vbox-debian7-64mda-2xdb.cfg │ └── vbox-debian7-64mda.cfg ├── helper.rb ├── options │ ├── common.rb │ └── postgres.rb ├── setup │ ├── early │ │ └── 00_remove_previous_config.rb │ ├── post_suite │ │ ├── 01_validate_database.rb │ │ ├── 10_collect_artifacts.rb │ │ └── 99_teardown.rb │ └── pre_suite │ │ ├── 00_setup_test_env.rb │ │ ├── 05_clear_firewalls.rb │ │ ├── 10_setup_proxies.rb │ │ ├── 20_install_puppet.rb │ │ ├── 30_generate_ssl_certs.rb │ │ ├── 40_install_deps.rb │ │ ├── 50_install_modules.rb │ │ ├── 70_install_released_puppetdb.rb │ │ ├── 75_clean_out_puppet5_repos.rb │ │ ├── 80_add_dev_repo.rb │ │ └── 90_install_devel_puppetdb.rb └── tests │ ├── commands │ ├── args-handling.rb │ ├── delete_reports.rb │ └── list-sub-commands.rb │ ├── security │ └── puppetdb-ssl-setup │ │ ├── jetty-changes.rb │ │ ├── no-puppet-certs.rb │ │ └── nonprod-environment.rb │ └── smoke.rb ├── ci ├── README.md └── bin │ ├── prep-and-run-in │ ├── run │ └── travis-on-success ├── config.sample.ini ├── config └── image_templates │ └── ec2.yaml ├── contrib ├── README.md └── gem │ ├── Gemfile │ ├── README.md │ └── puppetdb-terminus.gemspec ├── dev-docs ├── README.md ├── partitioning.markdown ├── release │ └── reconciliation.md └── run-pdb-on-macos.md ├── dev-resources ├── Makefile.i18n ├── jdk11on-fips-security ├── jdk8-fips-security ├── suppression.xml └── time-shift-export │ └── input-archive │ ├── catalogs │ └── catalog.json │ ├── export-metadata.json │ ├── facts │ └── facts.json │ └── reports │ └── report.json ├── documentation ├── CONTRIBUTING.md ├── README.md ├── _puppetdb_nav.html ├── acceptance_tests.markdown ├── anonymization.markdown ├── api │ ├── admin │ │ └── v1 │ │ │ ├── archive.markdown │ │ │ ├── cmd.markdown │ │ │ └── summary-stats.markdown │ ├── command │ │ └── v1 │ │ │ └── commands.markdown │ ├── ext │ │ └── v1 │ │ │ ├── managed-packages.markdown │ │ │ ├── resource-graphs.markdown │ │ │ └── state-overview.markdown │ ├── meta │ │ └── v1 │ │ │ ├── server-time.markdown │ │ │ └── version.markdown │ ├── metrics │ │ └── v2 │ │ │ └── jolokia.markdown │ ├── overview.markdown │ ├── query │ │ ├── curl.markdown │ │ ├── examples-pql.markdown │ │ ├── tutorial-pql.markdown │ │ ├── tutorial.markdown │ │ └── v4 │ │ │ ├── aggregate-event-counts.markdown │ │ │ ├── ast.markdown │ │ │ ├── catalog_input_contents.markdown │ │ │ ├── catalog_inputs.markdown │ │ │ ├── catalogs.markdown │ │ │ ├── edges.markdown │ │ │ ├── entities.markdown │ │ │ ├── environments.markdown │ │ │ ├── event-counts.markdown │ │ │ ├── events.markdown │ │ │ ├── fact-contents.markdown │ │ │ ├── fact-names.markdown │ │ │ ├── fact-paths.markdown │ │ │ ├── facts.markdown │ │ │ ├── factsets.markdown │ │ │ ├── inventory.markdown │ │ │ ├── nodes.markdown │ │ │ ├── overview.markdown │ │ │ ├── packages.markdown │ │ │ ├── paging.markdown │ │ │ ├── pql.markdown │ │ │ ├── producers.markdown │ │ │ ├── query.markdown │ │ │ ├── reports.markdown │ │ │ ├── resources.markdown │ │ │ └── upgrading-from-v3.markdown │ ├── status │ │ └── v1 │ │ │ └── status.markdown │ └── wire_format │ │ ├── catalog_format_v6.markdown │ │ ├── catalog_format_v7.markdown │ │ ├── catalog_format_v8.markdown │ │ ├── catalog_format_v9.markdown │ │ ├── catalog_inputs_format_v1.markdown │ │ ├── configure_expiration_format_v1.markdown │ │ ├── deactivate_node_format_v3.markdown │ │ ├── facts_format_v4.markdown │ │ ├── facts_format_v5.markdown │ │ ├── report_format_v5.markdown │ │ ├── report_format_v6.markdown │ │ ├── report_format_v7.markdown │ │ └── report_format_v8.markdown ├── community_add_ons.markdown ├── configure.markdown ├── configure_postgres.markdown ├── connect_puppet_apply.markdown ├── connect_puppet_server.markdown ├── ha.markdown ├── images │ ├── pdb_erd.png │ ├── perf-dash-large.png │ └── perf-dash-small.png ├── install_from_packages.markdown ├── install_from_source.markdown ├── install_via_module.markdown ├── known_issues.markdown ├── load_testing_tool.markdown ├── logging.markdown ├── maintain_and_tune.markdown ├── migration_coordination.markdown ├── overview.markdown ├── pdb_client_tools.markdown ├── pdb_support_guide.markdown ├── postgres_ssl.markdown ├── puppetdb-faq.markdown ├── puppetdb.ditamap ├── puppetdb_connection.markdown ├── release_notes.markdown ├── release_notes_5.2.markdown ├── release_notes_6.0.markdown ├── release_notes_6.3.markdown ├── release_notes_6.markdown ├── release_notes_7.markdown ├── release_notes_8.markdown ├── release_notes_older.markdown ├── repl.markdown ├── scaling_recommendations.markdown ├── testing_storage_changes.markdown ├── trouble_session_logging.markdown ├── upgrade.markdown ├── using.markdown └── versioning_policy.markdown ├── eastwood.clj ├── ext ├── .gitignore ├── bin │ ├── analyze-index-usage │ ├── boxed-core-tests │ ├── boxed-integration-tests │ ├── check-command-perf │ ├── check-spec-env │ ├── clj-1.11 │ ├── config-puppet-test-ref │ ├── config-puppetserver-test-ref │ ├── contributors-in-git-log │ ├── dep-diff │ ├── flavor-from-spec │ ├── host-info │ ├── jdk-from-spec │ ├── jdk-info │ ├── locust-load-tests-aggregator │ ├── pdbbox-env │ ├── pdbbox-init │ ├── prefixed-ref-from-spec │ ├── prep-debianish │ ├── prep-debianish-root │ ├── prep-macos │ ├── render-pdb-schema │ ├── require-jdk │ ├── require-leiningen │ ├── require-pgbox │ ├── run-external-tests │ ├── run-locust-load-tests │ ├── run-normal-tests │ ├── run-rspec-tests │ ├── sha256sum │ ├── spec-includes │ ├── symlink-relative-to │ ├── tag-release │ ├── test-config │ ├── with-pdbbox │ └── wrtrepo ├── build_defaults.yaml ├── jenkins │ ├── beaker-tests-source.sh │ ├── beaker-tests.sh │ ├── lein-test.sh │ ├── packaging.sh │ └── terminus-rspec.sh ├── project_data.yaml ├── test-conf │ ├── pgver-default │ ├── puppet-ref-default │ └── puppetserver-ref-default └── test │ ├── database-migration-config │ ├── oom-causes-shutdown │ ├── schema-mismatch-causes-pdb-shutdown │ ├── top-level-cli │ └── upgrade-and-exit ├── locales ├── eo.po └── puppetdb.pot ├── locust ├── load-test │ ├── cd4pe.yaml │ ├── console.yaml │ ├── estate-reporting.yaml │ ├── example.yaml │ └── load-test.py └── run-load-test ├── pdb ├── project.clj ├── puppet ├── lib │ └── puppet │ │ ├── face │ │ └── node │ │ │ ├── deactivate.rb │ │ │ └── status.rb │ │ ├── functions │ │ └── puppetdb_query.rb │ │ ├── indirector │ │ ├── catalog │ │ │ └── puppetdb.rb │ │ ├── facts │ │ │ ├── puppetdb.rb │ │ │ └── puppetdb_apply.rb │ │ ├── node │ │ │ └── puppetdb.rb │ │ └── resource │ │ │ └── puppetdb.rb │ │ ├── reports │ │ └── puppetdb.rb │ │ └── util │ │ ├── puppetdb.rb │ │ └── puppetdb │ │ ├── atom.rb │ │ ├── char_encoding.rb │ │ ├── command.rb │ │ ├── command_names.rb │ │ ├── config.rb │ │ └── http.rb └── spec │ ├── README.markdown │ ├── spec.opts │ ├── spec_helper.rb │ └── unit │ ├── face │ └── node │ │ ├── deactivate_spec.rb │ │ └── status_spec.rb │ ├── indirector │ ├── catalog │ │ └── puppetdb_spec.rb │ ├── facts │ │ ├── puppetdb_apply_spec.rb │ │ └── puppetdb_spec.rb │ ├── node │ │ └── puppetdb_spec.rb │ └── resource │ │ └── puppetdb_spec.rb │ ├── reports │ └── puppetdb_spec.rb │ └── util │ ├── puppetdb │ ├── char_encoding_spec.rb │ ├── command_spec.rb │ ├── config_spec.rb │ └── http_spec.rb │ └── puppetdb_spec.rb ├── resources ├── ext │ ├── cli │ │ ├── anonymize │ │ ├── config-migration │ │ ├── delete-reports.erb │ │ ├── ssl-setup.erb │ │ └── upgrade │ ├── config │ │ ├── bootstrap.cfg │ │ ├── conf.d │ │ │ ├── auth.conf │ │ │ ├── config.ini │ │ │ ├── database.ini │ │ │ ├── jetty.ini │ │ │ └── repl.ini │ │ ├── logback.xml │ │ └── request-logging.xml │ ├── docs │ └── ezbake.conf ├── logback.xml ├── public │ └── dashboard │ │ ├── charts.js │ │ ├── d3.v2.js │ │ ├── d3.v5.js │ │ └── index.html └── puppetlabs │ └── puppetdb │ ├── benchmark │ ├── config.ini │ └── samples │ │ ├── catalogs │ │ ├── host-0.json │ │ ├── host-1.json │ │ └── host-2.json │ │ ├── facts │ │ ├── pg1.vm.json │ │ ├── pg2.vm.json │ │ └── puppetdb1.vm.json │ │ └── reports │ │ ├── pg1.vm-304bebf8e5fc109ced84e8b086f9bcf8324f3d78.json │ │ ├── pg1.vm-327147ee71a6e67db76112add34d49c674f97b4f.json │ │ ├── pg1.vm-339914cdb0a7a9a7ca4c9c310ab96ba20649376f.json │ │ ├── pg1.vm-9956b77aba1f29fe276978cd68d4c169f2e34d69.json │ │ ├── pg1.vm-a454ec51cbadba8c31beb9c1d66e90e9482ff4a6.json │ │ ├── pg2.vm-193c2a3ae8b277158dbb1073a35290b406c3c073.json │ │ ├── pg2.vm-19fce4fd5281b1df9b42d58c808fecb2a783da3b.json │ │ ├── pg2.vm-34ecfe5dcfebc9510d159d2ec010d6e1f9094fb1.json │ │ ├── pg2.vm-b73c37f620703406b5666e7c919afff00c511f1e.json │ │ ├── pg2.vm-bb3cea0e4f72a38fde935e93a9efca44e540ec3c.json │ │ ├── pg2.vm-cfdc33f7bb68d2c25d3b3758f3dca50b851b96ea.json │ │ ├── puppetdb1.vm-02f72d7b1e2ded2074c4c3d6e2f415f6978d5932.json │ │ ├── puppetdb1.vm-05ce58a44a6441dc967559bf89fd82619068f72c.json │ │ ├── puppetdb1.vm-5ba2c61aeb5f3ed8722e45f9c2c7b53d606e402e.json │ │ ├── puppetdb1.vm-6eade546c696f0c045ec29f955bdb4d6a39a8291.json │ │ └── puppetdb1.vm-9eeca12cedb235b2e8f616967bf1f46d3e1de812.json │ ├── bootstrap.cfg │ ├── generate │ ├── realistic │ │ ├── README.md │ │ ├── catalogs │ │ │ ├── host-gumozu-2-1a66541e7b9b051d8c7991d8a00eea4ed394bdaf.json │ │ │ ├── host-gygahy-0-3f3f7a46208584fbd5d8a8b399c1e3b976911c94.json │ │ │ ├── host-ryrure-4-b1f993dd750d31a3e94b976aa50a979b77957f89.json │ │ │ ├── host-tynahu-1-c7fc1e91b45c5ba6ef7dbd3792476e797cdb8e14.json │ │ │ └── host-wetowa-3-dd4541655ec202afbeb145d4dd012c967a50f937.json │ │ ├── facts │ │ │ ├── host-gumozu-2.json │ │ │ ├── host-gygahy-0.json │ │ │ ├── host-ryrure-4.json │ │ │ ├── host-tynahu-1.json │ │ │ └── host-wetowa-3.json │ │ ├── metadata.txt │ │ └── reports │ │ │ ├── host-gumozu-2-129b8aa47512e912a3219deb52d93c21ffee5d87.json │ │ │ ├── host-gumozu-2-242498540117a9110137818ff7cd4736b7d38b21.json │ │ │ ├── host-gumozu-2-2c9573717a180595c6d816e4ab52df60b0a7ffa1.json │ │ │ ├── host-gumozu-2-3b3381ecdbd115b32f5679514a983e36e32af731.json │ │ │ ├── host-gumozu-2-47167603410000bf19aa3fb788cdfbb1e62996b6.json │ │ │ ├── host-gumozu-2-4adaffefcd85a855d19256b12f4daa907219fac2.json │ │ │ ├── host-gumozu-2-55c1d33c06fd894c1edfd979b912bbe83fc01ef4.json │ │ │ ├── host-gumozu-2-58b3ccdf860f6f287d047f299f28601e8bfce95b.json │ │ │ ├── host-gumozu-2-5fa02edfb7a7861c363196e837327d9b194afba8.json │ │ │ ├── host-gumozu-2-6b71dce201813958e6a4d26fcc7e86b75016f151.json │ │ │ ├── host-gumozu-2-6fd3460c19ae9ed7c0c7711e745e0d30da9939d0.json │ │ │ ├── host-gumozu-2-70096ac447b722cf97cf83bc51fa63f5401dd050.json │ │ │ ├── host-gumozu-2-8aa91a013cd9bbd77701152e708d570dd5df42e0.json │ │ │ ├── host-gumozu-2-ab686f7fa9c66c8b0d67ac4ff0941d09bdddb4f1.json │ │ │ ├── host-gumozu-2-abfba7a5ab80e7c0dd3cdc28d7dc50550667c835.json │ │ │ ├── host-gumozu-2-c4f3bcca7c43c4249be37b4afac6f9bb9bfb857d.json │ │ │ ├── host-gumozu-2-c771226108d9ce7ef4ca48b92efbfd1176c0df4d.json │ │ │ ├── host-gumozu-2-da40895210e7845ecee7002c46a100f04724f10a.json │ │ │ ├── host-gumozu-2-f28e3d9af85cef45b96e6df3cee2f71b1bc6cfc8.json │ │ │ ├── host-gumozu-2-f6ef7eccefe78729bed4af47d8154dd8382927eb.json │ │ │ ├── host-gygahy-0-1051925dad799752b5289d9477106e24fa1f1af4.json │ │ │ ├── host-gygahy-0-4004f9810ecad68490167d3622160923d5b29725.json │ │ │ ├── host-gygahy-0-5846de90b9a273d533add2e639747abdc988b702.json │ │ │ ├── host-gygahy-0-601f4124578456a232da536b51ece130aabd7d8b.json │ │ │ ├── host-gygahy-0-6c05d9ff691f771af9442994e637ba076c9dab98.json │ │ │ ├── host-gygahy-0-7d91ea01a27db9b89cb2372ae1dbf79a5a4b9b97.json │ │ │ ├── host-gygahy-0-8319ea333b5c0331799cbeec2b3ba6ad32728926.json │ │ │ ├── host-gygahy-0-ad205634cbf17d67e4645542f75f96db1e5d58d9.json │ │ │ ├── host-gygahy-0-b2cc609555f6c556928794ee1f429b83429b8d41.json │ │ │ ├── host-gygahy-0-b642f6e3164eb43a825ebf74ff2f8e316f3bfadd.json │ │ │ ├── host-gygahy-0-b9905c0f77c5663cbbc2fb73c20124e278403ab7.json │ │ │ ├── host-gygahy-0-be98f57e018affd5de6b9c0576d0bb6d32ef776c.json │ │ │ ├── host-gygahy-0-caddfe49731096256388efb0d39fc050dc6339c2.json │ │ │ ├── host-gygahy-0-cb6ffa5478a3ec0ae12b834112fc9b3935a9c097.json │ │ │ ├── host-gygahy-0-e0a35bd868fb60ad3bcc168180a1165079dd60fc.json │ │ │ ├── host-gygahy-0-e43e5bf9a53de8797fe2ea53316bcc79d9b60437.json │ │ │ ├── host-gygahy-0-e95b5548b3090494d9c33986ef7fc4e59c7d020d.json │ │ │ ├── host-gygahy-0-f0baf1c5373d21c1bac177a939ffd8315f21b97c.json │ │ │ ├── host-gygahy-0-f2560763423b8509dcef6d672facddb5378d8d60.json │ │ │ ├── host-gygahy-0-f5255086871eb2feb8ca71438b42a5f7203266e8.json │ │ │ ├── host-ryrure-4-16835dd936d82742b78cc2ff56f42294a1f16e8b.json │ │ │ ├── host-ryrure-4-18b3fab78dc0ea1eeef7d83770649b7cd0049dbc.json │ │ │ ├── host-ryrure-4-1d4a6adf69cf7cdfadc5740cce7b2a47053dd288.json │ │ │ ├── host-ryrure-4-23319a65b2d27510833f0e974813e99589ec89ab.json │ │ │ ├── host-ryrure-4-28ab4d74d460c48b1356712a023bc319de4dd9e0.json │ │ │ ├── host-ryrure-4-322ca2cab16baf8ac6de39aba45e32b0393684f9.json │ │ │ ├── host-ryrure-4-453074857a1f08da57a582cc6702e833a8a02cab.json │ │ │ ├── host-ryrure-4-4d7496e9ed6f93b215e4c5829b41f51124f718ce.json │ │ │ ├── host-ryrure-4-5237c7b64fb26d561c56fab7f1e96da64ca5b95d.json │ │ │ ├── host-ryrure-4-67cfbddd146764313b73c995d5f4f4d2809a505f.json │ │ │ ├── host-ryrure-4-68a64306f4085441c665ffdf5b894345474d8426.json │ │ │ ├── host-ryrure-4-6d8502cb2da074983c07cd8f1679e8c53b23e1b6.json │ │ │ ├── host-ryrure-4-78805d860cd54a62379842344b97f7e00a402ffc.json │ │ │ ├── host-ryrure-4-936035df9c85fbd3ffa3847c5c15a6e40242025e.json │ │ │ ├── host-ryrure-4-a4c073e75964155dead02d53fc4b949d4e693914.json │ │ │ ├── host-ryrure-4-a588d0c919e8058e5258e72989251a461e27155e.json │ │ │ ├── host-ryrure-4-e9ca697832081961d9b625758fdf1e958eeefcd2.json │ │ │ ├── host-ryrure-4-e9e5f3e2c5d49138564df088e69f7b92934cb51c.json │ │ │ ├── host-ryrure-4-f406f7706f13a86bbec0d2051659e040886bf5c9.json │ │ │ ├── host-ryrure-4-fa2cdae56485670f8b54d8512b6b7950a463db00.json │ │ │ ├── host-tynahu-1-0cc32bc3629ee36b7893afc102454220d3ba5214.json │ │ │ ├── host-tynahu-1-0e7deaea35be34a02c5eba7ca7da21faee19f657.json │ │ │ ├── host-tynahu-1-129e8f712b7123530bdc1d7e37c2414c8d1d52d8.json │ │ │ ├── host-tynahu-1-14fbd73f7fd82738095fece4bc1e9006d21ccbca.json │ │ │ ├── host-tynahu-1-1616d07a1b3386700a9d9c47f756ce3c6d720919.json │ │ │ ├── host-tynahu-1-1d5f729c0360ecde5f288c3c3148349aeca20c3e.json │ │ │ ├── host-tynahu-1-2c7ee6ed5ee163b0d219b909660c092d47bf22a8.json │ │ │ ├── host-tynahu-1-2e6af94d7c4d10c407823c06b580323a58525033.json │ │ │ ├── host-tynahu-1-33c32ad4c40b000e8070e0078d1a2a5001945f27.json │ │ │ ├── host-tynahu-1-3669010d97fdb647e29b23065f94192ab8e88799.json │ │ │ ├── host-tynahu-1-4228a49a26665494e09658d46e8ade98e6f8d009.json │ │ │ ├── host-tynahu-1-576af8bde9249e51d84fe1ede196d2c82984fe40.json │ │ │ ├── host-tynahu-1-5ef4a2852fffe1f564b3bdd60585bdc765c9e4bf.json │ │ │ ├── host-tynahu-1-6bf02aaccc6335c010061658ddc491930eeada2c.json │ │ │ ├── host-tynahu-1-89343477dae7e7baf57d53fc9a1669423f1b6853.json │ │ │ ├── host-tynahu-1-ba599aba9a889cc86d61170ec68d7cdb53b9a1a3.json │ │ │ ├── host-tynahu-1-be433b41b21c71688aa5e3ec3c996d3755280ef0.json │ │ │ ├── host-tynahu-1-c19852f4328a6819cc93bcdc557280bbef80f4c5.json │ │ │ ├── host-tynahu-1-c9ca7c6a978348c91f40d73d52de41eccc9d2b2a.json │ │ │ ├── host-tynahu-1-eb88d7da1afa430d606954b2a5354078c4e79596.json │ │ │ ├── host-wetowa-3-30d3b1dfb11c3ad4d0d28be467da827170987670.json │ │ │ ├── host-wetowa-3-408bdcbee9f0f1fb79c54166592b2997a579d759.json │ │ │ ├── host-wetowa-3-55572957003738df47c962397feb8221a1a41144.json │ │ │ ├── host-wetowa-3-6379f93ecd8df737a8caf5bb9fbd5be4eef22299.json │ │ │ ├── host-wetowa-3-7238906a425e42a41c9cccbb675c48c2092b083e.json │ │ │ ├── host-wetowa-3-7612984f2c28868414b8d8a3861dd8683ee91bd2.json │ │ │ ├── host-wetowa-3-7908f83bfbe165252f0eea410dda94ba3aa00530.json │ │ │ ├── host-wetowa-3-7e5fa4804e42d51febcab0fa3298a2d3603fb51f.json │ │ │ ├── host-wetowa-3-80add03947a47b3ed55f715fbc8c692c1fea9e08.json │ │ │ ├── host-wetowa-3-80c53d8fada791edfafaf19ee21c5d659f6014f1.json │ │ │ ├── host-wetowa-3-87234da9d9d8a46ea29c2e820020218de609ec6e.json │ │ │ ├── host-wetowa-3-8aa772b4116e1b6ac54a2ee50b79e66f5f989c0e.json │ │ │ ├── host-wetowa-3-978e472e37d4d76c22a067e382eee69b01558ac2.json │ │ │ ├── host-wetowa-3-b135c291191b14dc88f086beb2dedeb870edfcf8.json │ │ │ ├── host-wetowa-3-b213b352873d3b0f2d5632cb6dc649a54780fb2e.json │ │ │ ├── host-wetowa-3-bc26d64d922f5f11f6bc41e719f2311516a36f45.json │ │ │ ├── host-wetowa-3-c10deff7ef2d21d4ccb67757c4ac3712ad66eaec.json │ │ │ ├── host-wetowa-3-cb4e4d7573d9177eb00babe5d259f5434c082ae1.json │ │ │ ├── host-wetowa-3-e2aff90bc1709a7fb9ea9d1a8b31ac38b210cc08.json │ │ │ └── host-wetowa-3-fa4cf470ac6af6896ab85ba1941c47be0e12b25e.json │ └── samples │ │ └── facts │ │ └── baseline-agent-node.json │ ├── pql │ └── pql-grammar.ebnf │ └── sample │ └── queries.edn ├── src └── puppetlabs │ ├── puppetdb.clj │ └── puppetdb │ ├── admin.clj │ ├── anonymizer.clj │ ├── archive.clj │ ├── catalog │ └── utils.clj │ ├── catalogs.clj │ ├── cheshire.clj │ ├── cli │ ├── benchmark.clj │ ├── benchmark │ │ └── query.clj │ ├── fact_storage_benchmark.clj │ ├── generate.clj │ ├── pdb_dataset.clj │ ├── services.clj │ ├── time_shift_export.clj │ ├── tk_util.clj │ ├── util.clj │ └── version.clj │ ├── client.clj │ ├── command.clj │ ├── command │ ├── constants.clj │ └── dlo.clj │ ├── config.clj │ ├── constants.clj │ ├── core.clj │ ├── dashboard.clj │ ├── export.clj │ ├── facts.clj │ ├── factsets.clj │ ├── honeysql.clj │ ├── http.clj │ ├── http │ ├── command.clj │ ├── handlers.clj │ ├── query.clj │ └── server.clj │ ├── import.clj │ ├── jdbc.clj │ ├── jdbc │ └── internal.clj │ ├── lint.clj │ ├── meta.clj │ ├── meta │ └── version.clj │ ├── metrics │ └── core.clj │ ├── middleware.clj │ ├── mq.clj │ ├── nio.clj │ ├── nodes.clj │ ├── package_util.clj │ ├── pdb_routing.clj │ ├── pql.clj │ ├── pql │ └── transform.clj │ ├── query.clj │ ├── query │ ├── aggregate_event_counts.clj │ ├── catalog_inputs.clj │ ├── common.clj │ ├── edges.clj │ ├── event_counts.clj │ ├── events.clj │ ├── fact_contents.clj │ ├── facts.clj │ ├── monitor.clj │ ├── paging.clj │ ├── population.clj │ ├── resources.clj │ └── summary_stats.clj │ ├── query_eng.clj │ ├── query_eng │ ├── default_reports.clj │ ├── engine.clj │ └── parse.clj │ ├── queue.clj │ ├── random.clj │ ├── reports.clj │ ├── scf │ ├── hash.clj │ ├── migrate.clj │ ├── partitioning.clj │ ├── storage.clj │ └── storage_utils.clj │ ├── schema.clj │ ├── status.clj │ ├── threadpool.clj │ ├── time.clj │ ├── utils.clj │ ├── utils │ ├── metrics.clj │ └── string_formatter.clj │ ├── zip.clj │ └── zip │ └── visit.clj ├── test-resources ├── binary-template.erb ├── ca.pem ├── create-test-db.sh ├── integration-bootstrap.cfg ├── integration-puppetdb.conf ├── localhost.key ├── localhost.pem ├── logback-test.xml ├── puppetlabs │ └── puppetdb │ │ ├── cli │ │ └── export │ │ │ ├── catalog-query-rows.json │ │ │ ├── reports-query-rows.json │ │ │ ├── sample-report.json │ │ │ └── tiny-catalog.json │ │ └── ssl │ │ ├── certs │ │ ├── ca.pem │ │ └── localhost.pem │ │ ├── private_keys │ │ ├── keyonly.pem │ │ └── localhost.pem │ │ └── public_keys │ │ └── localhost.pem └── puppetserver │ ├── bootstrap-7.x.cfg │ ├── bootstrap.cfg │ ├── logback-dev.xml │ ├── puppet.conf │ ├── puppetserver.conf │ ├── request-logging-dev.xml │ ├── rich_data_environment.conf │ ├── rich_data_puppet.conf │ └── ssl │ ├── ca │ ├── ca_crl.pem │ ├── ca_crt.pem │ ├── ca_key.pem │ ├── ca_pub.pem │ ├── inventory.txt │ ├── serial │ └── signed │ │ └── localhost.pem │ ├── certs │ ├── ca.pem │ └── localhost.pem │ ├── crl.pem │ ├── private_keys │ └── localhost.pem │ └── public_keys │ └── localhost.pem ├── test └── puppetlabs │ └── puppetdb │ ├── acceptance │ └── node_ttl.clj │ ├── admin_clean_test.clj │ ├── admin_test.clj │ ├── anonymizer_test.clj │ ├── archive_test.clj │ ├── catalog │ └── utils_test.clj │ ├── catalogs_test.clj │ ├── cheshire_test.clj │ ├── cli │ ├── benchmark_test.clj │ ├── generate_test.clj │ ├── pdb_dataset_test.clj │ ├── services_test.clj │ ├── time_shift_export_test.clj │ └── util_test.clj │ ├── command │ └── dlo_test.clj │ ├── command_broadcast_test.clj │ ├── command_test.clj │ ├── config_test.clj │ ├── core_test.clj │ ├── dashboard_test.clj │ ├── dev │ └── lein.clj │ ├── examples.clj │ ├── examples │ └── reports.clj │ ├── facts_test.clj │ ├── generative │ ├── generators.clj │ ├── overridable_generators.clj │ ├── overrideable_generators_test.clj │ └── submit_command.clj │ ├── http │ ├── aggregate_event_counts_test.clj │ ├── catalog_input_contents_test.clj │ ├── catalog_inputs_test.clj │ ├── catalogs_test.clj │ ├── command_test.clj │ ├── environments_test.clj │ ├── event_counts_test.clj │ ├── events_test.clj │ ├── explore_test.clj │ ├── facts_test.clj │ ├── index_test.clj │ ├── inventory_test.clj │ ├── nodes_test.clj │ ├── packages_test.clj │ ├── paging_test.clj │ ├── producers_test.clj │ ├── query_logging_test.clj │ ├── query_test.clj │ ├── reports_test.clj │ ├── resources_test.clj │ └── sync_version_checking.clj │ ├── http_test.clj │ ├── integration │ ├── exported_resources.clj │ ├── file_with_binary_template.clj │ ├── fixtures.clj │ ├── inventory.clj │ ├── masterless.clj │ ├── puppetserver_metrics.clj │ ├── reports.clj │ ├── resource_events.clj │ ├── sensitive_params.clj │ ├── smoke.clj │ ├── terminus_failover.clj │ └── time_shift_export.clj │ ├── jdbc_test.clj │ ├── meta │ └── version_test.clj │ ├── meta_test.clj │ ├── middleware_test.clj │ ├── migration_coordination_test.clj │ ├── pdb_routing_test.clj │ ├── pql │ ├── parser_test.clj │ └── transform_test.clj │ ├── pql_test.clj │ ├── query │ ├── events_test.clj │ ├── monitor_test.clj │ ├── population_test.clj │ └── regression_test.clj │ ├── query_eng │ ├── default_reports_test.clj │ └── parse_test.clj │ ├── query_eng_test.clj │ ├── query_timeout_test.clj │ ├── queue_test.clj │ ├── random_test.clj │ ├── reports_test.clj │ ├── scf │ ├── hash_test.clj │ ├── migrate_partitioning_test.clj │ ├── migrate_test.clj │ ├── sql_test.clj │ ├── storage_test.clj │ └── storage_utils_test.clj │ ├── schema_test.clj │ ├── status_test.clj │ ├── test_import.clj │ ├── test_in_parallel.clj │ ├── test_protocols.clj │ ├── testutils.clj │ ├── testutils │ ├── catalog_inputs.clj │ ├── catalogs.clj │ ├── cli.clj │ ├── dashboard.clj │ ├── db.clj │ ├── events.clj │ ├── facts.clj │ ├── http.clj │ ├── log.clj │ ├── mem.clj │ ├── nio.clj │ ├── nodes.clj │ ├── parse_yaml.clj │ ├── queue.clj │ ├── repl.clj │ ├── reports.clj │ ├── resources.clj │ ├── services.clj │ └── tar.clj │ ├── threadpool_test.clj │ ├── time_test.clj │ ├── utils │ ├── metrics_test.clj │ └── string_formatter_test.clj │ ├── utils_test.clj │ └── zip_test.clj └── util ├── bin └── pdb └── pdb ├── README.md ├── commands.py ├── pdb ├── puppetdb.py ├── requirements.txt └── samples /.clj-kondo/config.edn: -------------------------------------------------------------------------------- 1 | 2 | {:hooks 3 | {:analyze-call 4 | {clojure.test.check.clojure-test/defspec hooks/defspec 5 | murphy/with-final hooks/with-final 6 | puppetlabs.puppetdb.command-test/with-message-handler hooks/one-binding-then-body 7 | puppetlabs.puppetdb.http.explore-test/check-json-response hooks/check-json-response 8 | puppetlabs.puppetdb.jdbc-test/deftest-antonyms hooks/deftest-antonyms 9 | puppetlabs.puppetdb.testutils.http/deftest-http-app hooks/deftest-http-app 10 | puppetlabs.puppetdb.testutils.queue/with-stockpile hooks/one-binding-then-body 11 | puppetlabs.puppetdb.testutils/with-coordinated-fn hooks/with-coordinated-fn 12 | puppetlabs.trapperkeeper.core/defservice hooks/defservice 13 | puppetlabs.trapperkeeper.core/service hooks/service 14 | puppetlabs.trapperkeeper.services/defservice hooks/defservice 15 | puppetlabs.trapperkeeper.testutils.logging/with-log-output hooks/one-binding-then-body 16 | puppetlabs.trapperkeeper.testutils.logging/with-logged-event-maps hooks/one-binding-then-body 17 | puppetlabs.trapperkeeper.testutils.webserver/with-test-webserver hooks/with-test-webserver}} 18 | :lint-as 19 | {murphy/try! clojure.core/try 20 | puppetlabs.puppetdb.schema/defn-validated schema.core/defn 21 | puppetlabs.puppetdb.testutils/dotestseq clojure.core/doseq 22 | puppetlabs.puppetdb.testutils/with-wrapped-fn-args clojure.core/let 23 | puppetlabs.puppetdb.scf.storage-test/deftest-db clojure.test/deftest} 24 | :linters 25 | {:deprecated-var 26 | {:exclude 27 | {puppetlabs.puppetdb.jdbc/call-with-array-converted-query-rows {:namespaces [".*"]} 28 | puppetlabs.puppetdb.testutils.services/call-with-puppetdb-instance {:namespaces [".*"]} 29 | puppetlabs.puppetdb.testutils.services/with-puppetdb-instance {:namespaces [".*"]}}} 30 | :refer-all {:exclude [clojure.test]} 31 | :unresolved-symbol 32 | {:exclude 33 | [(puppetlabs.comidi/GET) 34 | (puppetlabs.comidi/POST)]}}} 35 | -------------------------------------------------------------------------------- /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ((clojure-mode 2 | (clojure-docstring-fill-column . 79) 3 | (eval . (put-clojure-indent 'try! 0)))) 4 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !.git 3 | !project.clj 4 | !src 5 | !resources 6 | !documentation 7 | !docker 8 | !test 9 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | docker/** text eol=lf 2 | resources/** text eol=lf 3 | -------------------------------------------------------------------------------- /.github/workflows/docs_publish.yml: -------------------------------------------------------------------------------- 1 | name: PuppetDB docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - doc-latest 7 | - doc-7.y 8 | - doc-6.y 9 | 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build-dita: 14 | name: Build HTML and upload to s3 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Initialize 18 | uses: actions/checkout@v2 19 | 20 | - name: Clone puppet-docs-dita-ot 21 | run: | 22 | git clone https://${{ secrets.TECHPUBS_GITHUB_TOKEN }}:x-oauth-basic@github.com/puppetlabs/puppet-docs-dita-ot.git --branch main 23 | - name: Set up Ruby 24 | uses: ruby/setup-ruby@v1 25 | with: 26 | ruby-version: 2.7.1 27 | bundler-cache: true 28 | env: 29 | BUNDLE_GEMFILE: puppet-docs-dita-ot/Gemfile 30 | BUNDLE_WITHOUT: references 31 | 32 | - name: Configure AWS credentials 33 | uses: aws-actions/configure-aws-credentials@v1 34 | with: 35 | aws-access-key-id: ${{ secrets.TECHPUBS_AWS_ACCESS_KEY_ID }} 36 | aws-secret-access-key: ${{ secrets.TECHPUBS_AWS_SECRET_ACCESS_KEY }} 37 | aws-region: us-west-2 38 | 39 | - name: Build docs 40 | env: 41 | GIT_HUB_TOKEN: ${{ secrets.TECHPUBS_GITHUB_TOKEN }} 42 | BUNDLE_GEMFILE: puppet-docs-dita-ot/Gemfile 43 | SLACK_TOKEN: ${{ secrets.TECHPUBS_SLACK_TOKEN }} 44 | DOCS_LOCAL_DEV: false 45 | run: bundle exec rake -f puppet-docs-dita-ot/Rakefile build_html\[puppet-docs-dita-ot/prod.yaml\] 46 | 47 | - name: Trigger Netlify 48 | run: curl -X POST ${{ secrets.NETLIFY_PROD }} 49 | 50 | - name: Notify Slack if the build fails 51 | if: ${{ failure() }} 52 | run: >- 53 | curl -X POST -H 'Content-type: application/json' 54 | --data '{"text":"*Build failed*\n 55 | _User:_ '"$GITHUB_ACTOR"'\n 56 | _Repo:_ '"$GITHUB_REPOSITORY"'\n 57 | _Branch:_ '"$GITHUB_REF"'\n 58 | _Commit link:_ '"https://github.com/$GITHUB_REPOSITORY/commit/$GITHUB_SHA"'"}' 59 | ${{ secrets.SLACK_WEBHOOK }} 60 | -------------------------------------------------------------------------------- /.github/workflows/docs_test.yml: -------------------------------------------------------------------------------- 1 | name: Docs test 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - 'documentation/**/*' 7 | 8 | jobs: 9 | run-dita: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Initialize 14 | uses: actions/checkout@v2 15 | 16 | - name: Docs test 17 | uses: dita-ot/dita-ot-action@master 18 | with: 19 | build: | 20 | dita -i documentation/puppetdb.ditamap -o out -f html5 --processing-mode=strict -------------------------------------------------------------------------------- /.github/workflows/jira.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Export issue to Jira 3 | 4 | on: 5 | issues: 6 | types: [labeled] 7 | 8 | permissions: 9 | issues: write 10 | 11 | jobs: 12 | export: 13 | uses: "puppetlabs/phoenix-github-actions/.github/workflows/jira.yml@main" 14 | with: 15 | jira-project: PDB 16 | jira-base-url: ${{ vars.jira_base_url }} 17 | jira-user-email: ${{ vars.jira_user_email }} 18 | secrets: 19 | jira-api-token: ${{ secrets.JIRA_ISSUES_ACTION }} 20 | -------------------------------------------------------------------------------- /.github/workflows/mend.yaml: -------------------------------------------------------------------------------- 1 | name: mend_scan 2 | on: 3 | workflow_dispatch: 4 | push: 5 | branches: 6 | - main 7 | - 7.x 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: connect_twingate 13 | uses: twingate/github-action@v1 14 | with: 15 | service-key: ${{ secrets.TWINGATE_PUBLIC_REPO_KEY }} 16 | - name: checkout repo content 17 | uses: actions/checkout@v2 # checkout the repository content to github runner. 18 | with: 19 | fetch-depth: 1 20 | # install java which is required for mend and clojure 21 | - name: setup java 22 | uses: actions/setup-java@v3 23 | with: 24 | distribution: temurin 25 | java-version: 17 26 | # install clojure tools 27 | - name: Install Clojure tools 28 | uses: DeLaGuardo/setup-clojure@12.5 29 | with: 30 | # Install just one or all simultaneously 31 | # The value must indicate a particular version of the tool, or use 'latest' 32 | # to always provision the latest version 33 | cli: latest # Clojure CLI based on tools.deps 34 | lein: latest # Leiningen 35 | boot: latest # Boot.clj 36 | bb: latest # Babashka 37 | clj-kondo: latest # Clj-kondo 38 | cljstyle: latest # cljstyle 39 | zprint: latest # zprint 40 | # run lein gen 41 | - name: create pom.xml 42 | run: lein pom 43 | # download mend 44 | - name: download_mend 45 | run: curl -o wss-unified-agent.jar https://unified-agent.s3.amazonaws.com/wss-unified-agent.jar 46 | - name: run mend 47 | run: env WS_INCLUDES=pom.xml java -jar wss-unified-agent.jar 48 | env: 49 | WS_APIKEY: ${{ secrets.MEND_API_KEY }} 50 | WS_WSS_URL: https://saas-eu.whitesourcesoftware.com/agent 51 | WS_USERKEY: ${{ secrets.MEND_TOKEN }} 52 | WS_PRODUCTNAME: Puppet Enterprise 53 | WS_PROJECTNAME: ${{ github.event.repository.name }} 54 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Leiningen 3 | /target/ 4 | /target-gems/ 5 | /pom.xml 6 | 7 | # Acceptance tests 8 | /junit/ 9 | /log/ 10 | 11 | # Emacs 12 | *# 13 | *~ 14 | .#* 15 | 16 | # Local overide for testing config 17 | /test-resources/config/local.clj 18 | 19 | # Vagrant 20 | /.vagrant/ 21 | 22 | # A generalized temporary area for local use, tmp for 23 | # general temporary items, and scripts for any local 24 | # scripts. 25 | /tmp 26 | /scripts 27 | 28 | # Bundler files 29 | /vendor 30 | /Gemfile.lock 31 | 32 | # Used by Puppet Labs packaging system 33 | /ext/packaging/ 34 | 35 | # VIM swap files 36 | *.swp 37 | 38 | # The leiningen temporary/local files 39 | .lein-failures 40 | .lein-deps-sum 41 | .lein-repl-history 42 | 43 | # lein-checkouts folder 44 | checkouts 45 | 46 | # RVM files for localised setups 47 | .ruby-gemset 48 | .ruby-version 49 | 50 | # clj-i18n 51 | /resources/puppetlabs/puppetdb/*.class 52 | /resources/locales.clj 53 | /mp-* 54 | /dev-resources/i18n/bin 55 | 56 | /.bundle/ 57 | /ext/test-conf/pgbin-requested 58 | /ext/test-conf/pgport-requested 59 | /ext/test-conf/pgver-requested 60 | /ext/test-conf/puppet-ref-requested 61 | /ext/test-conf/puppetserver-dep 62 | /ext/test-conf/puppetserver-ref-requested 63 | /puppet/state/ 64 | /puppetserver/ 65 | 66 | /.clj-kondo/.cache/ 67 | /.eastwood 68 | /.nrepl-port 69 | /pdb.bcpkix 70 | /pdb.bcprov 71 | 72 | # locust output files and python cache 73 | *.csv 74 | *report.html 75 | locust/load-test/__pycache__/ 76 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Claire Cadman claire cadman 2 | Claire Cadman clairecadman 3 | Heston Hoffman hestonhoffman 4 | 5 | Zak Kent Zak-Kent 6 | Zak Kent 7 | Jean Bond jbondpdx 8 | Ethan J. Brown Iristyle 9 | Cas Donoghue donoghuc 10 | Michelle Fredette MFredette 11 | Jonathan Newman jonathannewman 12 | Eric Newton <95654936+rileynewton@users.noreply.github.com> 13 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @puppetlabs/dumpling @puppetlabs/skeletor 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include dev-resources/Makefile.i18n 2 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | PuppetDB - Centralized Puppet Storage 2 | Copyright 2011-2016 Puppet Inc 3 | 4 | This product includes software developed at Puppet Inc (http://puppet.com/). 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this software except in compliance with the License. 8 | You may obtain a copy of the License at: 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PuppetDB [![Build Status](https://app.travis-ci.com/puppetlabs/puppetdb.svg?branch=main)](https://app.travis-ci.com/puppetlabs/puppetdb) 2 | 3 | [docs]: https://docs.puppet.com/puppetdb/latest 4 | [contributing]: documentation/CONTRIBUTING.md 5 | [users]: https://groups.google.com/forum/#!forum/puppet-users 6 | 7 | PuppetDB is the fast, scalable, and reliable data warehouse for Puppet. It caches data generated by Puppet, and gives you advanced features at awesome speed with a powerful API. 8 | 9 | For documentation on this product, consult the [latest documentation][docs]. 10 | 11 | ## Contributing 12 | 13 | If you would like to contribute to PuppetDB, please take a look at our [contributing doc][contributing]. 14 | 15 | ## Maintenance 16 | 17 | Community Help: [Puppet Users Mailing List][users], [Puppet Community Portal](https://puppet.com/community) 18 | 19 | Tickets: [https://tickets.puppet.com/browse/PDB](https://tickets.puppet.com/browse/PDB) 20 | -------------------------------------------------------------------------------- /acceptance/config/ec2-west-el7-64mda-el7-64a.cfg: -------------------------------------------------------------------------------- 1 | HOSTS: 2 | el7-64-1: 3 | roles: 4 | - master 5 | - database 6 | - dashboard 7 | - agent 8 | vmname: el-7-x86_64-west 9 | platform: el-7-x86_64 10 | amisize: c3.large 11 | hypervisor: ec2 12 | snapshot: foss 13 | el7-64-2: 14 | roles: 15 | - agent 16 | vmname: el-7-x86_64-west 17 | platform: el-7-x86_64 18 | amisize: c3.large 19 | hypervisor: ec2 20 | snapshot: foss 21 | CONFIG: 22 | nfs_server: none 23 | consoleport: 443 24 | vpc_id: vpc-3cb28658 25 | subnet_ids: 26 | - subnet-8990e3ff 27 | - subnet-11d78c75 28 | - subnet-afaa18f7 29 | -------------------------------------------------------------------------------- /acceptance/config/vbox-debian7-64mda-2xdb.cfg: -------------------------------------------------------------------------------- 1 | HOSTS: 2 | debian-7-amd64-1: 3 | roles: 4 | - master 5 | - agent 6 | - dashboard 7 | - database 8 | platform: debian-7-amd64 9 | hypervisor: vagrant 10 | box: debian-70rc1-x64-vbox4210-nocm 11 | box_url: http://puppet-vagrant-boxes.puppetlabs.com/debian-70rc1-x64-vbox4210-nocm.box 12 | debian-7-amd64-2: 13 | roles: 14 | - database 15 | platform: debian-7-amd64 16 | hypervisor: vagrant 17 | box: debian-70rc1-x64-vbox4210-nocm 18 | box_url: http://puppet-vagrant-boxes.puppetlabs.com/debian-70rc1-x64-vbox4210-nocm.box 19 | CONFIG: 20 | nfs_server: none 21 | consoleport: 443 22 | -------------------------------------------------------------------------------- /acceptance/config/vbox-debian7-64mda.cfg: -------------------------------------------------------------------------------- 1 | HOSTS: 2 | debian-7-amd64.vm: 3 | roles: 4 | - master 5 | - agent 6 | - dashboard 7 | - database 8 | platform: debian-7-amd64 9 | hypervisor: vagrant 10 | box: debian-70rc1-x64-vbox4210-nocm 11 | box_url: http://puppet-vagrant-boxes.puppetlabs.com/debian-70rc1-x64-vbox4210-nocm.box 12 | 13 | CONFIG: 14 | nfs_server: none 15 | consoleport: 443 16 | -------------------------------------------------------------------------------- /acceptance/options/common.rb: -------------------------------------------------------------------------------- 1 | def common_options_hash() 2 | dir = File.expand_path(File.join(File.dirname(__FILE__), '..')) 3 | 4 | { 5 | :helper => [File.join(dir, 'helper.rb')], 6 | :pre_suite => [File.join(dir, 'setup', 'early'), 7 | File.join(dir, 'setup', 'pre_suite')] 8 | } 9 | end 10 | -------------------------------------------------------------------------------- /acceptance/options/postgres.rb: -------------------------------------------------------------------------------- 1 | # We are eval'd in the scope of the acceptance framework's option-parsing 2 | # code, so we can't use __FILE__ to find our location. We have access to 3 | # a variable 'options_file_path', though. 4 | require File.expand_path(File.join(File.dirname(options_file_path), 'common.rb')) 5 | 6 | common_options_hash.tap do |my_hash| 7 | my_hash[:is_puppetserver] = 'true' 8 | my_hash[:'use-service'] = 'true' 9 | my_hash[:'puppetserver-confdir'] = '/etc/puppetlabs/puppetserver/conf.d' 10 | my_hash[:puppetservice] = 'puppetserver' 11 | end 12 | -------------------------------------------------------------------------------- /acceptance/setup/early/00_remove_previous_config.rb: -------------------------------------------------------------------------------- 1 | 2 | unless (options[:vmrun]) or (ENV['PUPPETDB_SKIP_PRESUITE_PROVISIONING']) 3 | step "Clean up configuration files on master" do 4 | on master, "rm -rf /etc/puppet/routes.yaml" 5 | end 6 | 7 | step "Clean up configuration files on puppetdb server" do 8 | on databases, "rm -rf /etc/puppetdb/ssl" 9 | end 10 | 11 | step "Remove old modules from master" do 12 | on master, "rm -rf /etc/puppet/modules/*" 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /acceptance/setup/post_suite/10_collect_artifacts.rb: -------------------------------------------------------------------------------- 1 | 2 | step "Create artifacts directory" do 3 | unless File.directory?('artifacts') 4 | Dir.mkdir("artifacts") 5 | end 6 | end 7 | step "Collect puppetdb log file" do 8 | 9 | scp_from(database, "/var/log/puppetlabs/puppetdb/puppetdb.log", "./artifacts") 10 | 11 | end 12 | -------------------------------------------------------------------------------- /acceptance/setup/post_suite/99_teardown.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | test_config = PuppetDBExtensions.config 4 | 5 | def uninstall_package(host, os_families, pkg_name) 6 | os = os_families[host.name] 7 | case os 8 | when :debian 9 | on(host, "apt-get -f -y purge #{pkg_name} ") 10 | when :redhat 11 | on(host, "yum -y remove #{pkg_name}") 12 | else 13 | raise ArgumentError, "Unsupported OS family: '#{os}'" 14 | end 15 | end 16 | 17 | 18 | step "Stop puppetdb" do 19 | stop_puppetdb(database) 20 | end 21 | 22 | if (test_config[:purge_after_run]) 23 | if (test_config[:install_type] == :package) 24 | step "Uninstall packages" do 25 | uninstall_package(database, test_config[:os_families], "puppetdb") 26 | uninstall_package(master, test_config[:os_families], "puppetdb-termini") 27 | hosts.each do |host| 28 | uninstall_package(host, test_config[:os_families], "puppet") 29 | end 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /acceptance/setup/pre_suite/00_setup_test_env.rb: -------------------------------------------------------------------------------- 1 | os_families = {} 2 | 3 | step "Determine host OS's" do 4 | os_families = hosts.inject({}) do |result, host| 5 | result[host.name] = get_os_family(host) 6 | result 7 | end 8 | end 9 | 10 | PuppetDBExtensions.initialize_test_config(options, 11 | os_families) 12 | -------------------------------------------------------------------------------- /acceptance/setup/pre_suite/05_clear_firewalls.rb: -------------------------------------------------------------------------------- 1 | unless (test_config[:skip_presuite_provisioning]) 2 | step "Flushing iptables chains" do 3 | hosts.each do |host| 4 | on host, 'apt-get install -y iptables' if (is_bullseye || is_bookworm) 5 | on host, "iptables -F INPUT -t filter" 6 | on host, "iptables -F FORWARD -t filter" 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /acceptance/setup/pre_suite/20_install_puppet.rb: -------------------------------------------------------------------------------- 1 | test_name "Install Puppet" do 2 | unless (test_config[:skip_presuite_provisioning]) 3 | if is_el8 && ([:upgrade_latest].include? test_config[:install_mode]) 4 | on(hosts, 'update-crypto-policies --set LEGACY') 5 | 6 | # Work around RedHat Bug 2224427 7 | on(hosts, 'yum install -y tzdata-java') 8 | end 9 | 10 | step "Install Puppet" do 11 | install_puppet(puppet_repo_version(test_config[:platform_version], 12 | test_config[:install_mode], 13 | test_config[:nightly])) 14 | end 15 | end 16 | 17 | step "Populate facts from each host" do 18 | populate_facts 19 | end 20 | 21 | pidfile = '/var/run/puppet/master.pid' 22 | 23 | master_facts = facts(master.name) 24 | 25 | if options[:type] == 'aio' then 26 | bounce_service( master, master['puppetservice'], 10 ) 27 | else 28 | with_puppet_running_on( 29 | master, 30 | :master => {:dns_alt_names => "puppet,#{master_facts['hostname']},#{master_facts['fqdn']}", 31 | :trace => 'true'}) do 32 | # PID file exists? 33 | step "PID file created?" do 34 | on master, "[ -f #{pidfile} ]" 35 | end 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /acceptance/setup/pre_suite/30_generate_ssl_certs.rb: -------------------------------------------------------------------------------- 1 | unless (test_config[:skip_presuite_provisioning]) 2 | step "Run an agent to create the SSL certs" do 3 | on( master, "chown -R puppet:puppet /opt/puppetlabs/puppet/cache") 4 | databases.each do |database| 5 | with_puppet_running_on(master, {'master' => {'autosign' => 'true', 'trace' => 'true'}}) do 6 | run_agent_on(database, "--test") 7 | end 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /acceptance/setup/pre_suite/50_install_modules.rb: -------------------------------------------------------------------------------- 1 | require 'beaker/dsl/install_utils' 2 | 3 | extend Beaker::DSL::InstallUtils 4 | 5 | unless (test_config[:skip_presuite_provisioning]) 6 | step "Install the puppetdb module and dependencies" do 7 | install_puppetdb_module(databases, puppet_repo_version(test_config[:platform_version], 8 | test_config[:install_mode], 9 | test_config[:nightly])) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /acceptance/setup/pre_suite/70_install_released_puppetdb.rb: -------------------------------------------------------------------------------- 1 | # We skip this step entirely unless we are running in :upgrade mode. 2 | version = test_config[:package_build_version].to_s 3 | latest_released = get_latest_released(version) 4 | 5 | if ([:upgrade_oldest, :upgrade_latest].include? test_config[:install_mode]) \ 6 | && !(test_config[:skip_presuite_provisioning]) 7 | 8 | install_target = test_config[:install_mode] == :upgrade_latest ? latest_released : oldest_supported 9 | step "Install most recent released PuppetDB on the PuppetDB server for upgrade test" do 10 | databases.each do |database| 11 | enable_https_apt_sources(database) 12 | install_puppetdb(database, install_target) 13 | start_puppetdb(database) 14 | install_puppetdb_termini(master, databases, install_target) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /acceptance/setup/pre_suite/75_clean_out_puppet5_repos.rb: -------------------------------------------------------------------------------- 1 | if (test_config[:install_mode] == :upgrade_oldest) \ 2 | && !(test_config[:skip_presuite_provisioning]) 3 | 4 | step "Clean out puppet6 repos to prepare for puppet7 upgrade" do 5 | # skip this step for bullseye beacause it only installs puppet7 in upgrade_oldest 6 | if test_config[:install_mode] == :upgrade_oldest 7 | databases.each do |database| 8 | 9 | # need to remove puppet6 repo to avoid conflicts when upgrading 10 | uninstall_package(database, "puppet7-release") 11 | 12 | databases.each do |host| 13 | os = test_config[:os_families][host.name] 14 | 15 | # On RedHat systems, java 8 is still higher priority than java 8 16 | # To avoid the upgrade failing, we "pre-upgrade" the server to java 11 17 | if os == :redhat 18 | install_package(host, 'java-11-openjdk-headless') 19 | on(database, "alternatives --set java /usr/lib/jvm/java-11-openjdk-*/bin/java") 20 | end 21 | end 22 | 23 | # This is an upgrade oldest test, but we are upgrading now and want the 24 | # latest platform so specify the :install type to get the proper puppet repo 25 | # 26 | # this upgrades puppet-agent and puppetserver packages 27 | install_puppet(puppet_repo_version(test_config[:platform_version], 28 | :install, 29 | test_config[:nightly])) 30 | 31 | on(database, puppet('resource', 'host', 'updates.puppetlabs.com', 'ensure=present', "ip=127.0.0.1") ) 32 | end 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /acceptance/setup/pre_suite/80_add_dev_repo.rb: -------------------------------------------------------------------------------- 1 | repo_config_dir = 'tmp/repo_configs' 2 | 3 | if (test_config[:install_type] == :package) \ 4 | && test_config[:package_build_version] \ 5 | && !(test_config[:skip_presuite_provisioning]) 6 | then 7 | # do not install the dev_repo if a package_build_version has not been specified. 8 | databases.each do |database| 9 | install_puppetlabs_dev_repo database, 'puppetdb', test_config[:package_build_version], 10 | repo_config_dir, options 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /acceptance/setup/pre_suite/90_install_devel_puppetdb.rb: -------------------------------------------------------------------------------- 1 | step "Install development build of PuppetDB on the PuppetDB server" do 2 | databases.each do |database| 3 | os = test_config[:os_families][database.name] 4 | 5 | case test_config[:install_type] 6 | when :git 7 | Log.notify("Install puppetdb from source") 8 | Log.error database 9 | 10 | enable_https_apt_sources(database) 11 | install_postgres(database) 12 | install_puppetdb_via_rake(database) 13 | start_puppetdb(database) 14 | when :package 15 | Log.notify("Installing puppetdb from package; install mode: '#{test_config[:install_mode].inspect}'") 16 | 17 | enable_https_apt_sources(database) 18 | install_puppetdb(database) 19 | 20 | if test_config[:validate_package_version] 21 | validate_package_version(database) 22 | end 23 | 24 | # The package should automatically start the service on debian. On redhat, 25 | # it doesn't. However, during test runs where we're doing package upgrades, 26 | # the redhat package *should* detect that the service was running before the 27 | # upgrade, and it should restart it automatically. 28 | # 29 | # That leaves the case where we're on a redhat box and we're running the 30 | # tests as :install only (as opposed to :upgrade). In that case we need 31 | # to start the service ourselves here. 32 | if test_config[:install_mode] == :install and [:redhat].include?(os) 33 | start_puppetdb(database) 34 | else 35 | # make sure it got started by the package install/upgrade 36 | sleep_until_started(database) 37 | end 38 | 39 | end 40 | end 41 | 42 | case test_config[:install_type] 43 | when :git 44 | install_puppetdb_termini_via_rake(master, databases) 45 | when :package 46 | install_puppetdb_termini(master, databases) 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /acceptance/tests/commands/args-handling.rb: -------------------------------------------------------------------------------- 1 | test_name "argument handling" do 2 | bin_loc = puppetdb_bin_dir(database) 3 | 4 | ["ssl-setup"].each do |k| 5 | step "running puppetdb #{k} -h should not error out" do 6 | on database, "#{bin_loc}/puppetdb #{k} -h" 7 | end 8 | 9 | # We don't test ssl-setup here, because its actions without any arguments 10 | # are tested elsewhere. 11 | next if k == 'ssl-setup' 12 | step "running puppetdb-#{k} with no arguments should not error out" do 13 | on database, "#{bin_loc}/puppetdb #{k}", :acceptable_exit_codes => [1] 14 | assert_match(/Missing required argument/, stdout) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /acceptance/tests/commands/delete_reports.rb: -------------------------------------------------------------------------------- 1 | test_name "test puppetdb delete" do 2 | step "clear puppetdb database" do 3 | clear_and_restart_puppetdb(database) 4 | end 5 | 6 | with_puppet_running_on master, { 7 | 'master' => { 8 | 'autosign' => 'true' 9 | }} do 10 | 11 | step "Run agents once to activate nodes" do 12 | run_agent_on agents, "--test --server #{master}" 13 | end 14 | end 15 | 16 | step "Verify the data was stored in PuppetDB" do 17 | check_record_count("nodes", agents.length) 18 | check_record_count("factsets", agents.length) 19 | check_record_count("catalogs", agents.length) 20 | check_record_count("reports", agents.length) 21 | end 22 | 23 | step "Run puppetdb delete-reports" do 24 | bin_loc = puppetdb_bin_dir(database) 25 | on(database, "#{bin_loc}/puppetdb delete-reports") 26 | end 27 | 28 | step "Verify puppetdb can still be queried" do 29 | check_record_count("nodes", agents.length) 30 | end 31 | 32 | step "Verify puppetdb has no reports" do 33 | check_record_count("reports", 0) 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /acceptance/tests/commands/list-sub-commands.rb: -------------------------------------------------------------------------------- 1 | test_name "list sub-commands" do 2 | bin_loc = puppetdb_bin_dir(database) 3 | 4 | step "running puppetdb on its own should list all sub-commands" do 5 | result = on database, "#{bin_loc}/puppetdb" 6 | ["delete-reports", "ssl-setup", "foreground"].each do |k| 7 | assert_match(/#{k}/, result.stdout, "puppetdb command should list #{k} as a sub-command") 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /acceptance/tests/security/puppetdb-ssl-setup/jetty-changes.rb: -------------------------------------------------------------------------------- 1 | test_name "puppetdb ssl-setup jetty.ini changes" do 2 | confd = "#{puppetdb_confdir(database)}/conf.d" 3 | bin_loc = "#{puppetdb_bin_dir(database)}" 4 | 5 | step "backup jetty.ini and setup template" do 6 | on database, "cp #{confd}/jetty.ini #{confd}/jetty.ini.bak.ssl_setup_tests" 7 | end 8 | 9 | step "check to make sure all settings were configured for jetty.ini" do 10 | ["ssl-host", "ssl-port", "ssl-key", "ssl-cert", "ssl-ca-cert"].each do |k| 11 | on database, "grep -e '^#{k} = ' #{confd}/jetty.ini" 12 | end 13 | end 14 | 15 | step "run puppetdb ssl-setup again to make sure it is idempotent" do 16 | on database, "#{bin_loc}/puppetdb ssl-setup" 17 | on database, "diff #{confd}/jetty.ini #{confd}/jetty.ini.bak.ssl_setup_tests" 18 | end 19 | 20 | step "purposely modify jetty.ini ssl-host and make sure puppetdb ssl-setup -f fixes it" do 21 | on database, "sed -i 's/^ssl-host = .*/ssl-host = foobarbaz/' #{confd}/jetty.ini" 22 | on database, "#{bin_loc}/puppetdb ssl-setup -f" 23 | on database, "grep -e '^ssl-host = foobarbaz' #{confd}/jetty.ini", :acceptable_exit_codes => [1] 24 | end 25 | 26 | step "purposely modify jetty.ini ssl-host and make sure puppetdb ssl-setup does not touch it" do 27 | on database, "sed -i 's/^ssl-host = .*/ssl-host = foobarbaz/' #{confd}/jetty.ini" 28 | on database, "#{bin_loc}/puppetdb ssl-setup" 29 | on database, "grep -e '^ssl-host = foobarbaz' #{confd}/jetty.ini" 30 | end 31 | 32 | step "restore original jetty.ini" do 33 | on database, "cp #{confd}/jetty.ini.bak.ssl_setup_tests #{confd}/jetty.ini" 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /acceptance/tests/security/puppetdb-ssl-setup/no-puppet-certs.rb: -------------------------------------------------------------------------------- 1 | test_name "puppetdb ssl-setup with no puppet certs" do 2 | db_conf_dir = puppetdb_confdir(database) 3 | db_ssl_dir = "#{db_conf_dir}/ssl" 4 | db_confd = "#{puppetdb_confdir(database)}/conf.d" 5 | bin_loc = "#{puppetdb_bin_dir(database)}" 6 | 7 | ssl_dir = on(database, "puppet config print ssldir --section master").stdout.chomp 8 | 9 | step "backup jetty.ini and puppetdb ssl certs" do 10 | on database, "cp #{db_confd}/jetty.ini #{db_confd}/jetty.ini.bak.ssl_setup_tests" 11 | on database, "rm -rf #{db_ssl_dir}.bak.ssl_setup_tests" 12 | on database, "if [ -e #{db_ssl_dir} ]; then mv #{db_ssl_dir} #{db_ssl_dir}.bak.ssl_setup_tests; fi" 13 | end 14 | 15 | teardown do 16 | on database, "cp #{db_confd}/jetty.ini.bak.ssl_setup_tests #{db_confd}/jetty.ini" 17 | # This restores the certs if they weren't restored already 18 | on database, "if [ ! -e #{ssl_dir} -a -e #{ssl_dir}.bak.ssl_setup_tests ]; then mv #{ssl_dir}.bak.ssl_setup_tests #{ssl_dir}; fi" 19 | on database, "if [ ! -e #{db_ssl_dir} -a -e #{db_ssl_dir}.bak.ssl_setup_tests ]; then mv #{db_ssl_dir}.bak.ssl_setup_tests #{db_ssl_dir}; fi" 20 | end 21 | 22 | # The goal of this test is, make sure the user receives a nice error when 23 | # the agent certs are missing, as this implies Puppet has not ran yet. 24 | step "run puppetdb ssl-setup with no puppet certs, and make sure it returns a meaningful error" do 25 | on database, "rm -rf #{ssl_dir}.bak.ssl_setup_tests" 26 | on database, "mv #{ssl_dir} #{ssl_dir}.bak.ssl_setup_tests" 27 | result = on database, "#{bin_loc}/puppetdb ssl-setup", :acceptable_exit_codes => [1] 28 | assert_match(/Warning: Unable to find all puppet certificates to copy/, result.output) 29 | end 30 | 31 | # Now we restore the certificates 32 | step "restore certificates" do 33 | on database, "rm -rf #{ssl_dir}" 34 | on database, "mv #{ssl_dir}.bak.ssl_setup_tests #{ssl_dir}" 35 | end 36 | 37 | step "retest puppetdb ssl-setup again now there are certs" do 38 | on database, "#{bin_loc}/puppetdb ssl-setup" 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /acceptance/tests/security/puppetdb-ssl-setup/nonprod-environment.rb: -------------------------------------------------------------------------------- 1 | test_name "puppetdb ssl-setup on nonproduction environment" do 2 | confdir = on(database, "puppet config print confdir --section master").stdout.chomp 3 | bin_loc = "#{puppetdb_bin_dir(database)}" 4 | step "back up existing puppet.conf" do 5 | on database, "cp #{confdir}/puppet.conf #{confdir}/puppet.conf.bak" 6 | end 7 | step "ensure proper exit code on ssl-setup" do 8 | on database, "puppet config set environment foo --section main" 9 | result = on database, "#{bin_loc}/puppetdb ssl-setup", :acceptable_exit_codes => [0] 10 | end 11 | step "restore original puppet.conf" do 12 | on database, "mv #{confdir}/puppet.conf.bak #{confdir}/puppet.conf" 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /acceptance/tests/smoke.rb: -------------------------------------------------------------------------------- 1 | test_name "test postgresql database restart handling to ensure we recover from a restart" do 2 | step "clear puppetdb database" do 3 | clear_and_restart_puppetdb(database) 4 | end 5 | 6 | with_puppet_running_on master, { 7 | 'master' => { 8 | 'autosign' => 'true' 9 | }} do 10 | 11 | step "Run agents once to activate nodes" do 12 | run_agent_on agents, "--test --server #{master}" 13 | end 14 | end 15 | 16 | step "Verify that the number of active nodes is what we expect" do 17 | check_record_count("nodes", agents.length) 18 | end 19 | 20 | step "Verify that one factset was stored for each node" do 21 | check_record_count("factsets", agents.length) 22 | end 23 | 24 | step "Verify that one catalog was stored for each node" do 25 | check_record_count("catalogs", agents.length) 26 | end 27 | 28 | step "Verify that one report was stored for each node" do 29 | check_record_count("reports", agents.length) 30 | end 31 | 32 | restart_puppetdb(database) 33 | 34 | step "Verify puppetdb can be queried after restarting" do 35 | check_record_count("nodes", agents.length) 36 | end 37 | 38 | restart_postgres(database) 39 | 40 | step "Verify puppetdb can be queried after restarting" do 41 | check_record_count("nodes", agents.length) 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /config.sample.ini: -------------------------------------------------------------------------------- 1 | # See README.md for more thorough explanations of each section and 2 | # option. 3 | 4 | [global] 5 | # Store mq/db data in a custom directory 6 | vardir = /var/lib/puppetdb 7 | 8 | # Use an external logback config file 9 | # logging-config = /path/to/logback.xml 10 | 11 | [puppetdb] 12 | # List of certificate names from which to allow incoming HTTPS requests: 13 | # certificate-allowlist = /path/to/certname/allowlist 14 | 15 | # Whether we should check for more recent PuppetDB versions. Defaults to 'false': 16 | # disable-update-checking = true 17 | 18 | [database] 19 | 20 | # Subname pattern: //host:port/databaseName 21 | #subname = //localhost:5432/puppetdb 22 | 23 | # Connect as a specific user 24 | # username = foobar 25 | 26 | # Use a specific password 27 | # password = foobar 28 | 29 | # How often (in minutes) to compact the database 30 | # gc-interval = 60 31 | 32 | [command-processing] 33 | # How many command-processing threads to use, defaults to (CPUs / 2) 34 | # threads = 4 35 | 36 | [jetty] 37 | # What host to listen on, defaults to binding to 'localhost' 38 | # host = foo.my.net 39 | 40 | # What port to listen on 41 | port = 8080 42 | 43 | [nrepl] 44 | # Set to true to enable the remote REPL 45 | enabled = false 46 | 47 | # What port the REPL should listen on 48 | port = 8082 49 | 50 | # IP address to listen on 51 | host = 127.0.0.1 52 | -------------------------------------------------------------------------------- /config/image_templates/ec2.yaml: -------------------------------------------------------------------------------- 1 | AMI: 2 | el-7-x86_64-west: 3 | :image: 4 | :pe: ami-c25448a3 5 | :foss: ami-c25448a3 6 | :region: us-west-2 7 | 8 | el-6-x86_64-west: 9 | :image: 10 | :pe: ami-aa8b039a 11 | :foss: ami-aa8b039a 12 | :region: us-west-2 13 | 14 | el-5-x86_64-west: 15 | :image: 16 | :pe: ami-85693fb5 17 | :foss: ami-85693fb5 18 | :region: us-west-2 19 | 20 | fedora-20-x86_64-west: 21 | :image: 22 | :pe: ami-c0b9daf0 23 | :foss: ami-c0b9daf0 24 | :region: us-west-2 25 | 26 | ubuntu-16.04-amd64-west: 27 | :image: 28 | :pe: ami-7a47b41a 29 | :foss: ami-7a47b41a 30 | :region: us-west-2 31 | 32 | ubuntu-15.10-amd64-west: 33 | :image: 34 | :pe: ami-ddad4dbd 35 | :foss: ami-ddad4dbd 36 | :region: us-west-2 37 | 38 | ubuntu-14.04-amd64-west: 39 | :image: 40 | :pe: ami-be524edf 41 | :foss: ami-be524edf 42 | :region: us-west-2 43 | 44 | ubuntu-12.04-amd64-west: 45 | :image: 46 | :pe: ami-d6e860e6 47 | :foss: ami-d6e860e6 48 | :region: us-west-2 49 | 50 | debian-8-amd64-west: 51 | :image: 52 | :pe: ami-17120727 53 | :foss: ami-17120727 54 | :region: us-west-2 55 | 56 | debian-7-amd64-west: 57 | :image: 58 | :pe: ami-6a574b0b 59 | :foss: ami-6a574b0b 60 | :region: us-west-2 61 | -------------------------------------------------------------------------------- /contrib/README.md: -------------------------------------------------------------------------------- 1 | # PuppetDB User-Contributed Content 2 | 3 | This directory contains code and other content that has been contributed by 4 | PuppetDB users. It's a place where we can include items that we know will be 5 | useful to other users, but that we can't yet officially maintain or support. 6 | We hope that you will find it valuable! 7 | 8 | Please keep in mind that the contents of this directory may not be exhaustively 9 | tested and could conceivably become out-of-sync with the main production code base. 10 | If you find something that is out of date or has any other issues, or if you have 11 | other content that you think may be useful to the community, we welcome additional 12 | submissions via github pull requests! 13 | -------------------------------------------------------------------------------- /contrib/gem/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in puppetdb-terminus.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /contrib/gem/README.md: -------------------------------------------------------------------------------- 1 | # PuppetDB Terminus Gemspec 2 | 3 | The files in this directory are intended to provide a starting point for 4 | building a gem package of the puppetdb terminus code. This will be useful 5 | for cases where puppet is being installed as a gem and you would also like to 6 | include puppetdb. 7 | 8 | Note that support for installing the puppetdb termini via rubygems relies on 9 | changes to the puppet autoloader that were first introduced in the 3.0 series. -------------------------------------------------------------------------------- /contrib/gem/puppetdb-terminus.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | 5 | Gem::Specification.new do |gem| 6 | gem.name = "puppetdb-terminus" 7 | gem.version = "3.0.0" 8 | gem.authors = ["Puppet Labs"] 9 | gem.email = ["puppet@puppetlabs.com"] 10 | gem.description = "Puppet terminus files to connect to PuppetDB" 11 | gem.summary = "Connect Puppet to PuppetDB by setting up a terminus for PuppetDB" 12 | gem.homepage = "https://github.com/puppetlabs/puppetdb" 13 | gem.license = "Apache-2.0" 14 | 15 | gem.files = Dir['LICENSE.txt', 'NOTICE.txt', 'README.md', 'puppet/lib/**/*', 'puppet/spec/**/*'] 16 | gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } 17 | gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) 18 | gem.require_paths = ["lib"] 19 | 20 | gem.add_runtime_dependency 'json' 21 | gem.add_runtime_dependency 'puppet', ['>= 3.8.1', '<5.0'] 22 | end 23 | -------------------------------------------------------------------------------- /dev-docs/README.md: -------------------------------------------------------------------------------- 1 | # Developer Documentation 2 | 3 | ## Table of Contents 4 | 5 | 1. Releases 6 | * [Reconciling Git commits and Jira Tickets](./release/reconciliation.md) 7 | -------------------------------------------------------------------------------- /dev-docs/run-pdb-on-macos.md: -------------------------------------------------------------------------------- 1 | ## Installing dependencies: 2 | **Jdk 11:** 3 | 4 | brew install openjdk@11 5 | 6 | After installing openjdk run: 7 | 8 | sudo ln -sfn /usr/local/opt/openjdk@11/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-11.jdk 9 | **Leiningen:** 10 | 11 | brew install leiningen 12 | 13 | **pgbox script** 14 | 15 | Download the [script](https://gitlab.com/pgbox-org/pgbox/-/blob/master/pgbox) locally and add it to your PATH 16 | 17 | In the project directory install project dependencies using Leiningen: 18 | 19 | lein install 20 | 21 | ## Running pdb 22 | Initialize a pdbbox environment: 23 | 24 | $ ext/bin/pdbbox-init \ 25 | --sandbox ./test-sandbox \ 26 | --pgbin /usr/local/bin \ 27 | --pgport 5432 \ 28 | --bind-addr 127.0.0.1 \ 29 | Run the project 30 | 31 | lein run services -c test-sandbox/conf.d 32 | -------------------------------------------------------------------------------- /dev-resources/suppression.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | ^pkg:maven/org\.clojure/core\.cache@.*$ 11 | CVE-2020-36448 12 | 13 | 14 | -------------------------------------------------------------------------------- /dev-resources/time-shift-export/input-archive/catalogs/catalog.json: -------------------------------------------------------------------------------- 1 | { 2 | "certname" : "host-8", 3 | "producer_timestamp" : "2021-05-13T11:10:00.000Z" 4 | } 5 | -------------------------------------------------------------------------------- /dev-resources/time-shift-export/input-archive/export-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "timestamp" : "2021-04-15T13:23:40.218Z", 3 | "command_versions" : { 4 | "replace_catalog" : 9, 5 | "store_report" : 8, 6 | "replace_facts" : 5, 7 | "configure_expiration" : 1, 8 | "replace_catalog_inputs" : 1 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /dev-resources/time-shift-export/input-archive/facts/facts.json: -------------------------------------------------------------------------------- 1 | { 2 | "certname" : "host-8", 3 | "producer_timestamp" : "2021-05-13T11:11:00.000Z" 4 | } 5 | -------------------------------------------------------------------------------- /dev-resources/time-shift-export/input-archive/reports/report.json: -------------------------------------------------------------------------------- 1 | { 2 | "logs" : [ { 3 | "file" : null, 4 | "line" : null, 5 | "tags" : [ "notice" ], 6 | "time" : "2021-05-13T11:11:01.000Z", 7 | "level" : "notice", 8 | "source" : "Puppet", 9 | "message" : "Finished catalog run in 0.35 seconds" 10 | }, { 11 | "file" : null, 12 | "line" : null, 13 | "tags" : [ "notice", "completed_stage", "main" ], 14 | "time" : "2021-05-13T11:10:00.000Z", 15 | "level" : "notice", 16 | "source" : "Stage[main]", 17 | "message" : "Would have triggered 'refresh' from 2 events" 18 | }], 19 | "start_time" : "2021-05-13T11:12:00.000Z", 20 | "certname" : "host-0", 21 | "producer_timestamp" : "2021-05-13T11:12:00.000Z", 22 | "end_time" : "2021-05-13T11:10:00.000Z", 23 | "resources" : [ { 24 | "corrective_change" : null, 25 | "events" : [ { 26 | "new_value" : "bar", 27 | "corrective_change" : null, 28 | "property" : "content", 29 | "name" : null, 30 | "old_value" : "foo", 31 | "status" : "success", 32 | "timestamp" : "2021-05-13T11:13:00.000Z", 33 | "message" : null 34 | } ], 35 | "file" : "/home/wyatt/.puppet/modules/concat/manifests/fragment.pp", 36 | "skipped" : false, 37 | "line" : 123, 38 | "resource_type" : "File", 39 | "resource_title" : "/home/wyatt/.puppet/var/concat/15-default-ssl.conf/fragments/10_default-ssl-docroot", 40 | "timestamp" : "2021-05-13T11:10:00.000Z", 41 | "containment_path" : [ "Stage[main]", "Loadtest", "Notify[foo]" ] 42 | } ] 43 | } 44 | -------------------------------------------------------------------------------- /documentation/README.md: -------------------------------------------------------------------------------- 1 | # PuppetDB documentation 2 | 3 | If you were redirected while trying to reach the PuppetDB docs at puppet.com/docs/puppetdb, the version you were trying to reach is no longer maintained. 4 | 5 | For the most recent PuppetDB docs, see [puppet.com/docs/puppetdb/latest](https://puppet.com/docs/puppetdb/latest). 6 | For a list of the current maintained versions of open source Puppet and its components, see the most recent [Puppet version](https://puppet.com/docs/puppet/latest/about_agent.html) information. 7 | For a list of supported Puppet Enterprise versions, see the [Puppet Enterprise lifecycle](https://puppet.com/misc/puppet-enterprise-lifecycle). 8 | 9 | If you need docs for an older version of PuppetDB, you may be able to find it by switching to the relevant branch of this repository. 10 | 11 | -------------------------------------------------------------------------------- /documentation/api/admin/v1/archive.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Archive endpoint" 3 | layout: default 4 | canonical: "/puppetdb/latest/api/admin/v1/archive.html" 5 | --- 6 | # Archive endpoint 7 | 8 | [curl]: ../../query/curl.markdown#using-curl-from-localhost-non-sslhttp 9 | 10 | The `/archive` endpoint can be used for importing and exporting PuppetDB 11 | archives. 12 | 13 | ## `POST /pdb/admin/v1/archive` 14 | 15 | This endpoint can be used for streaming a PuppetDB archive into PuppetDB. 16 | 17 | ### Request format 18 | 19 | The request should be a multipart POST and have `Content-Type: multipart/mixed`. 20 | 21 | ### URL parameters 22 | 23 | * `archive`: required. The archive file to import to the PuppetDB. This archive 24 | must have a file called `puppetdb-bak/metadata.json` as the first entry in the 25 | tarfile with a key `command_versions` which is a JSON object mapping PuppetDB 26 | command names to their version. 27 | 28 | ### Response format 29 | 30 | The response will be in `application/json`, and will return a JSON map upon 31 | successful completion of the importation: 32 | 33 | {"ok": true} 34 | 35 | ### Example 36 | 37 | [Using `curl` from localhost][curl]: 38 | 39 | curl -X POST http://localhost:8080/pdb/admin/v1/archive \ 40 | -F "archive=@example_backup_archive.tgz" 41 | 42 | {"ok": true} 43 | 44 | ## `GET /pdb/admin/v1/archive` 45 | 46 | This endpoint can be used to stream a tarred, gzipped backup archive of PuppetDB 47 | to your local machine. 48 | 49 | ### URL parameters 50 | 51 | * `anonymization_profile`: optional. The level of anonymization applied to the 52 | archive files. 53 | 54 | ### Response format 55 | 56 | The response will be a `application/octet-stream`, and will return a `tar.gz` 57 | archive. 58 | 59 | ### Example 60 | 61 | [Using `curl` from localhost][curl]: 62 | 63 | curl -X GET http://localhost:8080/pdb/admin/v1/archive -o puppetdb-export.tgz 64 | -------------------------------------------------------------------------------- /documentation/api/meta/v1/server-time.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Server time endpoint" 3 | layout: default 4 | canonical: "/puppetdb/latest/api/meta/v1/server-time.html" 5 | --- 6 | 7 | # Server time endpoint 8 | 9 | [curl]: ../../query/curl.markdown#using-curl-from-localhost-non-sslhttp 10 | 11 | The `/server-time` endpoint can be used to retrieve the server time from the PuppetDB server. 12 | 13 | ## `/pdb/meta/v1/server-time` 14 | 15 | This metadata endpoint will return the current time of the clock on the PuppetDB 16 | server. This can be useful as input to other time-based queries against PuppetDB, 17 | to eliminate the possibility of time differences between the clocks on client 18 | machines. 19 | 20 | This endpoint does not use any URL parameters or query strings. 21 | 22 | ### Response format 23 | 24 | The response will be in `application/json`, and will return a JSON map with a 25 | single key: `server_time`, whose value is an ISO-8601 representation of the 26 | current time on the PuppetDB server. 27 | 28 | {"server_time": "2013-09-20T20:54:27.472Z"} 29 | 30 | ### Example 31 | 32 | [Using `curl` from localhost][curl]: 33 | 34 | curl -X GET http://localhost:8080/pdb/meta/v1/server-time 35 | 36 | {"server_time": "2013-09-20T20:54:27.472Z"} 37 | 38 | -------------------------------------------------------------------------------- /documentation/api/meta/v1/version.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Version endpoint" 3 | layout: default 4 | canonical: "/puppetdb/latest/api/meta/v1/version.html" 5 | --- 6 | 7 | # Version endpoint 8 | 9 | [curl]: ../../query/curl.markdown#using-curl-from-localhost-non-sslhttp 10 | 11 | The `/version` endpoint can be used to retrieve version information from the PuppetDB server. 12 | 13 | ## `/pdb/meta/v1/version` 14 | 15 | This query endpoint will return version information about the running PuppetDB 16 | server. 17 | 18 | This endpoint does not use any URL parameters or query strings. 19 | 20 | ## `/pdb/meta/v1/version/latest` 21 | 22 | This query will display a message describing the latest version of PuppetDB. 23 | 24 | ### Response format 25 | 26 | The response will be in `application/json`, and will return a JSON map with a 27 | single key: `version`, whose value is a string representation of the version 28 | of the running PuppetDB server. 29 | 30 | {"version": "X.Y.Z"} 31 | 32 | ### Examples 33 | 34 | [Using `curl` from localhost][curl]: 35 | 36 | curl -X GET http://localhost:8080/pdb/meta/v1/version 37 | 38 | {"version": "X.Y.Z"} 39 | 40 | curl -X GET http://localhost:8080/pdb/meta/v1/version/latest 41 | 42 | { 43 | "newer" : false, 44 | "product" : "puppetdb", 45 | "link" : "https://docs.puppetlabs.com/puppetdb/2.3/release_notes.markdown", 46 | "message" : "Version 2.3.4 is now available!", 47 | "version" : "2.3.4" 48 | } 49 | -------------------------------------------------------------------------------- /documentation/api/query/v4/fact-names.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Fact-names endpoint" 3 | layout: default 4 | canonical: "/puppetdb/latest/api/query/v4/fact-names.html" 5 | --- 6 | # Fact-names endpoint 7 | 8 | [curl]: ../curl.markdown#using-curl-from-localhost-non-sslhttp 9 | [paging]: ./paging.markdown 10 | [query]: query.markdown 11 | 12 | The `/fact-names` endpoint can be used to retrieve all known fact names. 13 | 14 | ## `/pdb/query/v4/fact-names` 15 | 16 | This will return an alphabetical list of all known fact names, *including* those which are 17 | known only for deactivated nodes. 18 | 19 | ### URL parameters 20 | 21 | * `query`: optional. A JSON array containing the query in prefix notation 22 | (`["", "", ""]`). See the sections below for the 23 | supported operators and fields. For general info about queries, 24 | see [our guide to query structure.][query] 25 | 26 | If a query parameter is not provided, all results will be returned. 27 | 28 | ### Response format 29 | 30 | The response will be in `application/json`, and will contain an alphabetical 31 | JSON array containing fact names. Each fact name will appear only one time, 32 | regardless of how many nodes have that fact. 33 | 34 | [, , ..., , ] 35 | 36 | ### Examples 37 | 38 | [Using `curl` from localhost][curl]: 39 | 40 | curl -X GET http://localhost:8080/pdb/query/v4/fact-names 41 | 42 | ["kernel", "operatingsystem", "osfamily", "uptime"] 43 | 44 | ## Paging 45 | 46 | This query endpoint supports paged results via the common PuppetDB paging 47 | URL parameters. For more information, please see the documentation 48 | on [paging][paging]. 49 | 50 | -------------------------------------------------------------------------------- /documentation/api/wire_format/deactivate_node_format_v3.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Deactivate node wire format, version 3" 3 | layout: default 4 | canonical: "/puppetdb/latest/api/wire_format/deactivate_node_format_v3.html" 5 | --- 6 | 7 | # Deactivate node wire format - v3 8 | 9 | PuppetDB receives deactivate node commands from Puppet Servers in the following wire format. 10 | 11 | ## Deactivate node command format 12 | 13 | ### Version 14 | 15 | This is **version 3** of the deactivate node command. 16 | 17 | ### Encoding 18 | 19 | The command is serialized as JSON, which requires strict UTF-8 encoding. 20 | 21 | ### Upgrade notes 22 | 23 | Previous versions of this command required only the certname, as a raw JSON 24 | string. It is now formatted as a JSON map, and the `producer_timestamp` property 25 | has been added. 26 | 27 | ### Main data type: Deactivate node 28 | 29 | { 30 | "certname": , 31 | "producer_timestamp": 32 | } 33 | 34 | #### `certname` 35 | 36 | String. The name of the node for which the catalog was compiled. 37 | 38 | #### `producer_timestamp` 39 | 40 | DateTime. The time of command submission from the Puppet Server to PuppetDB, 41 | according to the clock on the Puppet Server. 42 | 43 | `producer_timestamp` is optional but *highly* recommended. When provided, it is 44 | used to determine the precedence between this command and other commands that 45 | modify the same node. This field is provided by, and should thus reflect the 46 | clock of, the Puppet Server. 47 | 48 | When `producer_timestamp` is not provided, the PuppetDB server's local time is 49 | used. If another command is received for a node while a non-timestamped 50 | "deactivate node" command is pending processing, the results are *undefined*. 51 | 52 | ### Data type: `` 53 | 54 | A JSON string. Because the command is UTF-8, these must also be UTF-8. 55 | 56 | ### Data type: `` 57 | 58 | A JSON string representing a date and time (with time zone), formatted based on 59 | the recommendations in ISO 8601. For example, for a UTC time, the string would be 60 | formatted as `YYYY-MM-DDThh:mm:ss.sssZ`. For non-UTC time, the `Z` may be replaced 61 | with `±hh:mm` to represent the specific timezone. 62 | -------------------------------------------------------------------------------- /documentation/api/wire_format/facts_format_v4.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Facts wire format, version 4" 3 | layout: default 4 | canonical: "/puppetdb/latest/api/wire_format/facts_format_v4.html" 5 | --- 6 | # Facts wire format - v4 7 | 8 | Facts are represented as JSON. Unless otherwise noted, `null` is not 9 | allowed anywhere in the set of facts. 10 | 11 | {"certname": , 12 | "environment": , 13 | "producer_timestamp": , 14 | "values": { 15 | : , 16 | ... 17 | } 18 | } 19 | 20 | The `"certname"` key is the certname the facts are associated with. 21 | 22 | The `"environment"` key is the environment associated to the node when the facts were collected. 23 | 24 | The `"values"` key points to a _JSON Object_ that represents the set 25 | of facts. Each key is the fact name, and the value is the fact value. 26 | 27 | The `"producer_timestamp"` key points to a timestamp reflecting 28 | the time of fact set submission from the Puppet Server to PuppetDB. 29 | 30 | Fact names and values **must** be strings. 31 | 32 | ## Encoding 33 | 34 | The entire fact set is expected to be valid JSON, which mandates UTF-8 35 | encoding. 36 | -------------------------------------------------------------------------------- /documentation/api/wire_format/facts_format_v5.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Facts wire format, version 5" 3 | layout: default 4 | canonical: "/puppetdb/latest/api/wire_format/facts_format_v5.html" 5 | --- 6 | 7 | # Facts wire format - v5 8 | 9 | Facts are represented as JSON. Unless otherwise noted, `null` is not 10 | allowed anywhere in the set of facts. 11 | 12 | {"certname": , 13 | "environment": , 14 | "producer_timestamp": , 15 | "producer": , 16 | "values": { 17 | : , 18 | ... 19 | }, 20 | "package_inventory": [, , ...] 21 | 22 | } 23 | 24 | The `"certname"` key is the certname the facts are associated with. 25 | 26 | The `"environment"` key is the environment associated to the node when the facts were collected. 27 | 28 | The `"values"` key points to a _JSON Object_ that represents the set 29 | of facts. Each key is the fact name, and the value is the fact value. 30 | 31 | The `"producer_timestamp"` key points to a timestamp reflecting 32 | the time of fact set submission from the Server to PuppetDB. 33 | 34 | The `"producer"` key is the certname of the Puppet Server that sent the fact set 35 | to PuppetDB. This field may be `null`. 36 | 37 | Fact names and values **must** be strings. 38 | 39 | The `"package_inventory"` keys is optional, if present, must be an array of . 40 | 41 | ## Encoding 42 | 43 | The entire fact set is expected to be valid JSON, which mandates UTF-8 44 | encoding. 45 | 46 | ### Data type: `` 47 | 48 | An array of three strings: 49 | 50 | [ "", "", "" ] 51 | -------------------------------------------------------------------------------- /documentation/images/pdb_erd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/puppetdb/2c2efc97da49502083c0aa8269f9d1ddd9cb9541/documentation/images/pdb_erd.png -------------------------------------------------------------------------------- /documentation/images/perf-dash-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/puppetdb/2c2efc97da49502083c0aa8269f9d1ddd9cb9541/documentation/images/perf-dash-large.png -------------------------------------------------------------------------------- /documentation/images/perf-dash-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/puppetdb/2c2efc97da49502083c0aa8269f9d1ddd9cb9541/documentation/images/perf-dash-small.png -------------------------------------------------------------------------------- /documentation/release_notes.markdown: -------------------------------------------------------------------------------- 1 | release_notes_8.markdown -------------------------------------------------------------------------------- /documentation/using.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Using PuppetDB" 3 | layout: default 4 | canonical: "/puppetdb/latest/using.html" 5 | --- 6 | 7 | # Using PuppetDB 8 | 9 | [exported]: https://puppet.com/docs/puppet/latest/lang_exported.html 10 | 11 | 12 | Currently, PuppetDB's primary use is enabling advanced Puppet features. As use becomes more widespread, we expect additional applications to be built on PuppetDB. 13 | 14 | If you wish to build applications on PuppetDB, see the navigation sidebar for links to the API specifications. 15 | 16 | ## Checking node status 17 | 18 | The PuppetDB plugins [installed on your Puppet Server(s)](./connect_puppet_server.markdown) include a `status` action for the `node` face. On your Puppet Server, run: 19 | 20 | $ sudo puppet node status 21 | 22 | where `` is the name of the node you wish to investigate. This will tell you whether the node is active, when its last catalog was submitted, and when its last facts were submitted. 23 | 24 | ## Using exported resources 25 | 26 | PuppetDB lets you use exported resources, which allows your nodes to publish information for use by other nodes. 27 | 28 | [Learn more about using exported resources here.][exported] 29 | 30 | -------------------------------------------------------------------------------- /ext/.gitignore: -------------------------------------------------------------------------------- 1 | files/* 2 | -------------------------------------------------------------------------------- /ext/bin/check-spec-env: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Sanity check for a PuppetDB test spec 4 | # Ensures that correct JDK is installed and test flavor is valid 5 | 6 | set -ueo pipefail 7 | 8 | usage() 9 | { 10 | echo "Usage: $(basename $0) SPEC" 11 | } 12 | 13 | misuse() 14 | { 15 | usage 1>&2 16 | exit 2 17 | } 18 | 19 | # Ensure version of JDK from spec is available 20 | verify-jdk() { 21 | local spec="$1" 22 | local actual_jdk expected_jdk 23 | expected_jdk="$(ext/bin/jdk-from-spec "$spec")" 24 | actual_jdk="$(ext/bin/jdk-info --print spec)" 25 | if test "$expected_jdk" != "$actual_jdk"; then 26 | printf "JDK in path %q is not what PDB_TEST specifies: %q\n" \ 27 | "$actual_jdk" "$expected_jdk" 1>&2 28 | exit 2 29 | fi 30 | } 31 | 32 | test $# -ne 1 && misuse 33 | 34 | # Ensure test kind/flavor from test spec is valid 35 | spec="$1" 36 | test_kind=$(ext/bin/flavor-from-spec "$spec") 37 | case "$test_kind" in 38 | core|ext|core+ext|int|lint) 39 | verify-jdk "$spec" 40 | ;; 41 | rspec) 42 | ;; 43 | *) 44 | echo "Unexpected test category: $test_kind" 1>&2 45 | exit 2 46 | ;; 47 | esac 48 | -------------------------------------------------------------------------------- /ext/bin/clj-1.11: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -ueo pipefail 4 | 5 | nopf() { set +o pipefail; } 6 | 7 | clojure_ver=1.11.2 8 | spec_ver=0.3.218 # spec.alpha 9 | specs_ver=0.2.62 # core.specs.alpha 10 | 11 | script_home="$(cd "$(dirname "$0")" && pwd)" 12 | 13 | find_jar_or_die() 14 | { 15 | local name="$1" ver="$2" 16 | jar="$((nopf; find ~/.m2 -name "$name-$ver.jar") | head -1)" 17 | if ! test "$jar"; then 18 | echo "error: can't find $name $ver in ~/.m2" 1>&2 19 | exit 2 20 | fi 21 | echo "$jar" 22 | } 23 | 24 | clj_jar="$(find_jar_or_die clojure "$clojure_ver")" 25 | spec_jar="$(find_jar_or_die spec.alpha "$spec_ver")" 26 | specs_jar="$(find_jar_or_die core.specs.alpha "$specs_ver")" 27 | 28 | exec java -cp "$clj_jar:$spec_jar:$specs_jar" clojure.main "$@" 29 | -------------------------------------------------------------------------------- /ext/bin/contributors-in-git-log: -------------------------------------------------------------------------------- 1 | """": # -*-python-*- 2 | command -v python3 > /dev/null && exec python3 "$0" "$@" 3 | command -v python2 > /dev/null && exec python2 "$0" "$@" 4 | echo "error: unable to find python3 or python2" 1>&2; exit 2 5 | """ 6 | 7 | # Given two git tags, prints out a list of contributors who authored commits in 8 | # that commit range. Alphabetically sorted by first name. Excludes CI commits. 9 | # Output is wrapped at 72 characters. 10 | # Ex: contributors-in-git-log 6.0.0..6.27.0 => Bob Ross, Dolly Parton, and John Cena 11 | 12 | from __future__ import print_function 13 | 14 | import os, re, sys 15 | from subprocess import check_output 16 | from textwrap import fill 17 | 18 | if len(sys.argv) != 2: 19 | print('Usage: contributors-in-git-log ', file=sys.stderr) 20 | print(' e.g.: contributors-in-git-log 6.0.0..6.0.1', file=sys.stderr) 21 | sys.exit(2) 22 | 23 | stdout = sys.stdout.buffer 24 | ignore = frozenset([b'Jenkins CI']) 25 | 26 | authors = check_output(('git', 'log', '--pretty=%aN', sys.argv[1])) 27 | authors = sorted(set(a for a in authors.splitlines() if a not in ignore)) 28 | 29 | if len(authors) == 1: 30 | stdout.write(authors[0]) 31 | else: 32 | out = b', '.join(authors[:-1]) + b', and ' + authors[-1] + b'\n' 33 | out = check_output(('fold', '-sw', '72'), input=out) 34 | out = re.sub(br' +$', b'', out, flags=re.MULTILINE) 35 | stdout.write(out) 36 | -------------------------------------------------------------------------------- /ext/bin/flavor-from-spec: -------------------------------------------------------------------------------- 1 | """": # -*-python-*- 2 | command -v python3 > /dev/null && exec python3 "$0" "$@" 3 | command -v python2 > /dev/null && exec python2 "$0" "$@" 4 | echo "error: unable to find python3 or python2" 1>&2; exit 2 5 | """ 6 | 7 | # For a given spec, finds the "flavor" 8 | # core/openjdk8/pg-9.6 => core 9 | # core+ext/openjdk11/pg-13 => core+ext 10 | 11 | from __future__ import print_function 12 | from sys import exit, stderr 13 | import os, sys 14 | 15 | valid_flavors = ('core', 'ext', 'core+ext', 'int', 'lint', 'rspec') 16 | 17 | def usage(stream): 18 | print('Usage: flavor-from-spec core/openjdk8/pg-9.6', file=stream) 19 | 20 | def misuse(): 21 | usage(stderr) 22 | exit(2) 23 | 24 | len(sys.argv) == 2 or misuse() 25 | orig_specs = sys.argv[1] 26 | specs = orig_specs.split('/') 27 | specs = [x for x in specs if x in valid_flavors] 28 | if len(specs) != 1: 29 | print('Invalid test flavor in spec:', repr(orig_specs), file=stderr) 30 | exit(2) 31 | print(specs[0]) 32 | -------------------------------------------------------------------------------- /ext/bin/host-info: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Prints out information about the host machine for testing logs 4 | 5 | set -uexo pipefail 6 | 7 | # Print out operating system information 8 | uname -a 9 | # Print out machine-specific hostname->IP address mappings 10 | cat /etc/hosts 11 | 12 | # Print out hostname memory information 13 | case "$OSTYPE" in 14 | darwin*|netbsd) 15 | hostname 16 | vm_stat -c 1 17 | sysctl -n machdep.cpu.brand_string 18 | system_profiler SPHardwareDataType 19 | ;; 20 | *) 21 | hostname --fqdn 22 | free -m 23 | free -h 24 | ;; 25 | esac 26 | 27 | # Print out detailed CPU information 28 | if test -e /proc/cpuinfo; then 29 | cat /proc/cpuinfo 30 | fi 31 | 32 | # Print out versions of critical testing software 33 | bash --version 34 | java -version || true 35 | lein version || true 36 | ruby --version || true 37 | bundle --version || true 38 | bundler --version || true 39 | pgbox --version || true 40 | -------------------------------------------------------------------------------- /ext/bin/jdk-from-spec: -------------------------------------------------------------------------------- 1 | """": # -*-python-*- 2 | command -v python3 > /dev/null && exec python3 "$0" "$@" 3 | command -v python2 > /dev/null && exec python2 "$0" "$@" 4 | echo "error: unable to find python3 or python2" 1>&2; exit 2 5 | """ 6 | 7 | # Gets the JDK package name from the spec string 8 | # jdk-from-spec core/openjdk8/pg-9.6 => openjdk8 9 | 10 | from __future__ import print_function 11 | from sys import exit, stderr 12 | import os, sys 13 | 14 | def usage(stream): 15 | print('Usage: jdk-from-spec core/openjdk8/pg-9.6', file=stream) 16 | 17 | def misuse(): 18 | usage(stderr) 19 | exit(2) 20 | 21 | len(sys.argv) == 2 or misuse() 22 | specs = sys.argv[1] 23 | specs = specs.split('/') 24 | specs = [x for x in specs if 'jdk' in x] 25 | len(specs) == 1 or misuse() 26 | print(specs[0]) 27 | -------------------------------------------------------------------------------- /ext/bin/pdbbox-env: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Runs a command using an existing PostgreSQL sandbox inside a PuppetDB sandbox 4 | # Requires pgbox to already be installed and on PATH 5 | # Sets up PuppetDB environment variables for PostgreSQL roles and passwords used for testing 6 | # PDBBOX environment variable must be set and contain the path to your PuppetDB sandbox 7 | # You should first create a PuppetDB sandbox with ext/bin/pdbbox-init 8 | 9 | set -ueo pipefail 10 | 11 | usage() { echo 'Usage: PDBBOX=BOX_DIR pdbbox-env CMD [ARG...]'; } 12 | 13 | # PDBBOX must be set to an existing PuppetDB sandbox directory 14 | # CMD must be at least one token 15 | if test "$#" -lt 1 -o -z "$PDBBOX"; then 16 | usage 1>&2 17 | exit 1 18 | fi 19 | 20 | pgport="$(cat "$PDBBOX/pg/port")" 21 | pghost="$(tail -1 "$PDBBOX/pg/bind-addrs")" 22 | 23 | # Set PGBOX to let pgbox command to know where PostgreSQL sandbox is located 24 | # PostgreSQL sandbox is expected to be in PuppetDB sandbox created with ext/bin/pdbbox-init 25 | export PGBOX="$PDBBOX/pg" 26 | # All environment variables below are loaded by puppetlabs.puppetdb.testutils.db/test-env 27 | export PDB_TEST_DB_HOST="$pghost" 28 | export PDB_TEST_DB_PORT="$pgport" 29 | export PDB_TEST_DB_USER=pdb_test 30 | # The passwords are read from files in the PuppetDB sandbox 31 | export PDB_TEST_DB_USER_PASSWORD="$(cat "$PDBBOX/test-pass")" 32 | export PDB_TEST_DB_READ=pdb_test_read 33 | export PDB_TEST_DB_READ_PASSWORD="$(cat "$PDBBOX/test-pass-read")" 34 | export PDB_TEST_DB_MIGRATOR=pdb_test_migrator 35 | export PDB_TEST_DB_MIGRATOR_PASSWORD="$(cat "$PDBBOX/test-pass-migrator")" 36 | export PDB_TEST_DB_ADMIN=pdb_test_admin 37 | export PDB_TEST_DB_ADMIN_PASSWORD="$(cat "$PDBBOX/test-pass-admin")" 38 | 39 | # Run provided command using PostgreSQL sandbox 40 | exec pgbox env "$@" 41 | -------------------------------------------------------------------------------- /ext/bin/prefixed-ref-from-spec: -------------------------------------------------------------------------------- 1 | """": # -*-python-*- 2 | command -v python3 > /dev/null && exec python3 "$0" "$@" 3 | command -v python2 > /dev/null && exec python2 "$0" "$@" 4 | echo "error: unable to find python3 or python2" 1>&2; exit 2 5 | """ 6 | 7 | # Parses a spec for a given prefix and returns the ref (version number) 8 | # Basically prints out everything after the prefix up to the next / or end of spec 9 | # prefixed-ref-from-spec core/openjdk8/pg-9.6 pg- => 9.6 10 | 11 | from __future__ import print_function 12 | from sys import exit, stderr 13 | import os, sys 14 | 15 | def usage(stream): 16 | print('Usage: prefixed-ref-from-spec .../pup-5.5.x/srv-5.3.x/pg-9.6 srv-', 17 | file=stream) 18 | 19 | def misuse(): 20 | usage(stderr) 21 | exit(2) 22 | 23 | len(sys.argv) == 3 or misuse() 24 | specs, prefix = sys.argv[1:] 25 | specs = specs.split('/') 26 | specs = [x for x in specs if x.startswith(prefix)] 27 | len(specs) == 1 or misuse() 28 | print(specs[0][len(prefix):]) 29 | -------------------------------------------------------------------------------- /ext/bin/prep-debianish: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Prepares Debian-like Linux machines for running PuppetDB tests 4 | # Installs JDK, Leiningen, and pgbox and creates 5 | # --for takes a test spec like core/openjdk8/pg-9.6 6 | 7 | set -uxeo pipefail 8 | 9 | usage() { 10 | echo 'Usage: $(basename "$0") --for PDB_TEST_SPEC --install DIR' 11 | } 12 | 13 | misuse() { usage 1>&2; exit 2; } 14 | 15 | # Validate arguments 16 | spec='' 17 | install='' 18 | while test $# -gt 0; do 19 | case "$1" in 20 | --install) 21 | test $# -gt 1 || misuse 22 | install="$2" 23 | shift 2 24 | ;; 25 | --for) 26 | test $# -gt 1 || misuse 27 | spec="$2" 28 | shift 2 29 | ;; 30 | *) misuse ;; 31 | esac 32 | done 33 | 34 | test "$spec" || misuse 35 | test "$install" || misuse 36 | flavor=$(ext/bin/flavor-from-spec "$spec") 37 | 38 | # If flavor is not recognized, do nothing 39 | case "$flavor" in 40 | core|ext|core+ext|int|lint) 41 | jdk="$(ext/bin/jdk-from-spec "$spec")" 42 | jdkver="${jdk##*jdk}" 43 | mkdir -p "$install" 44 | abs_install=$(cd "$install" && pwd) 45 | export PATH="$abs_install/bin:$PATH" 46 | # Install JDK using cache if within 24 hours of last installation 47 | ext/bin/require-jdk --expire "$jdk" "$abs_install" 48 | # Create testing script with updated PATH 49 | mkdir -p "$abs_install/etc" 50 | printf ' 51 | export JAVA_HOME=%q/jdk 52 | export PATH="$JAVA_HOME/bin:$PATH" 53 | export PATH=%q/bin:"$PATH" 54 | hash -r 55 | ' \ 56 | "$abs_install" "$abs_install" \ 57 | > "$abs_install"/etc/pdb-test-env 58 | source "$abs_install"/etc/pdb-test-env 59 | # Install leiningen and pgbox 60 | ext/bin/require-leiningen default "$abs_install" 61 | ext/bin/require-pgbox default "$abs_install" 62 | ;; 63 | esac 64 | -------------------------------------------------------------------------------- /ext/bin/require-leiningen: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Installs leiningen onto machine 4 | # Supports at least Debian and MacOS 5 | 6 | set -uexo pipefail 7 | 8 | script_home="$(cd "$(dirname "$0")" && pwd)" 9 | 10 | # Default leiningen version 11 | default=2.9.5 12 | 13 | cmdname="$(basename "$0")" 14 | 15 | usage() { echo "Usage: $cmdname VERSION INSTALLDIR_IF_NEEDED"; } 16 | 17 | misuse() { usage 1>&2; exit 2; } 18 | 19 | # Hashmap of leiningen checksums 20 | declare -A known_hash 21 | known_hash[2.9.1]=32acacc8354627724d27231bed8fa190d7df0356972e2fd44ca144c084ad4fc7 22 | known_hash[2.9.4]=1e21276bad56f4f8f8afd605ddf0c4d047a5244724a8dc6e13c6c55cc53b3fee 23 | known_hash[2.9.5]=79cc2c4aeddf829c393d31d80e6fddfd8b30cc1907a0e2f7cd73c93b300077f6 24 | 25 | # Verify two arguments were given 26 | test "$#" -eq 2 || misuse 27 | 28 | ver="$1" 29 | if test "$ver" = default; then 30 | ver="$default" 31 | fi 32 | 33 | install="$2" 34 | hash="${known_hash[$ver]}" 35 | 36 | # Exit if installed version is same as requested 37 | if command -v lein; then 38 | curver="$(lein version | cut -d' ' -f2)" 39 | if test "$curver" = "$ver"; then 40 | exit 0 41 | fi 42 | if test -x "$install/bin/lein"; then 43 | curver="$("$install/bin/lein" version | cut -d' ' -f2)" 44 | if test "$curver" = "$ver"; then 45 | exit 0 46 | fi 47 | fi 48 | fi 49 | 50 | # Verify checksum is known for requested version 51 | if test -z "$hash"; then 52 | echo "$cmdname: don't know sha256sum for $ver" 1>&2 53 | exit 2 54 | fi 55 | 56 | # Create temporary directory 57 | tmpdir="$(mktemp -d "$cmdname-XXXXXX")" 58 | tmpdir="$(cd "$tmpdir" && pwd)" 59 | trap "$(printf 'rm -rf %q' "$tmpdir")" EXIT 60 | 61 | # Download leiningen from GitHub release 62 | cd "$tmpdir" 63 | curl -O "https://raw.githubusercontent.com/technomancy/leiningen/$ver/bin/lein" 64 | obshash="$("$script_home/sha256sum" < lein | cut -d' ' -f1)" 65 | cd .. 66 | 67 | # Verify checksum of exectuable 68 | if test "$obshash" != "$hash"; then 69 | echo "$cmdname: sha256sum $obshash != $hash" 1>&2 70 | exit 2 71 | fi 72 | 73 | # Install leiningen 74 | mkdir -p "$install/bin" 75 | mv -i "$tmpdir/lein" "$install/bin" 76 | chmod +x "$install/bin/lein" 77 | -------------------------------------------------------------------------------- /ext/bin/require-pgbox: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Installs pgbox onto machine 4 | # Supports at least Debian and MacOS 5 | 6 | set -uexo pipefail 7 | 8 | script_home="$(cd "$(dirname "$0")" && pwd)" 9 | 10 | default=0.0.0 11 | 12 | cmdname="$(basename "$0")" 13 | 14 | usage() { echo "Usage: $cmdname VERSION INSTALLDIR_IF_NEEDED"; } 15 | 16 | misuse() { usage 1>&2; exit 2; } 17 | 18 | # Hashmap of pgbox checksums 19 | declare -A known_hash 20 | known_hash[0.0.0]=c4dd424ddbcaf33cb0d3ef51255943cbdd87446ea7bf220528441849de35cfef 21 | 22 | # Verify two arguments were given 23 | test "$#" -eq 2 || misuse 24 | 25 | ver="$1" 26 | if test "$ver" = default; then 27 | ver="$default" 28 | fi 29 | 30 | install="$2" 31 | hash="${known_hash[$ver]}" 32 | 33 | # Verify checksum is known for requested version 34 | if ! test "$hash"; then 35 | echo "$cmdname: don't know sha256sum for $ver" 1>&2 36 | exit 2 37 | fi 38 | 39 | # Exit if installed version is same as requested 40 | if command -v pgbox; then 41 | curver="$(pgbox version | cut -d' ' -f2)" 42 | if test "$curver" = "$ver"; then 43 | exit 0 44 | fi 45 | fi 46 | 47 | # Create temporary directory 48 | tmpdir="$(mktemp -d "$cmdname-XXXXXX")" 49 | tmpdir="$(cd "$tmpdir" && pwd)" 50 | trap "$(printf 'rm -rf %q' "$tmpdir")" EXIT 51 | 52 | # Download pgbox from GitLab releases 53 | cd "$tmpdir" 54 | curl -O "https://gitlab.com/pgbox-org/pgbox/raw/82e512d37a7c6c2ae72d1293ea98945eaaae51f4/pgbox" 55 | obshash="$("$script_home/sha256sum" < pgbox | cut -d' ' -f1)" 56 | cd .. 57 | 58 | # Verify checksum of pgbox executable 59 | if test "$obshash" != "$hash"; then 60 | echo "$cmdname: sha256sum $obshash != $hash" 1>&2 61 | exit 2 62 | fi 63 | 64 | # Install pgbox 65 | mkdir -p "$install/bin" 66 | mv -i "$tmpdir/pgbox" "$install/bin" 67 | chmod +x "$install/bin/pgbox" 68 | -------------------------------------------------------------------------------- /ext/bin/run-external-tests: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Creates a PuppetDB uberjar and runs tests against it 4 | 5 | set -ueo pipefail 6 | 7 | failures=0 8 | 9 | # Log failed command 10 | failure() { 11 | if test "$TERM"; then 12 | echo "===== $(tput setaf 1)FAILED:$(tput sgr 0) $@" 1>&2 13 | else 14 | echo "===== FAILED: $@" 1>&2 15 | fi 16 | ((failures++)) || true 17 | } 18 | 19 | # Log successful command 20 | success() { 21 | echo "===== OK: $@" 1>&2 22 | } 23 | 24 | # Run a command and log success or failure based on exit status 25 | run() { 26 | echo -e "\n===== testing $@" 1>&2 27 | rc=0 28 | "$@" || rc=$? 29 | if test "$rc" -eq 0; then 30 | success "$@" 31 | else 32 | failure "$@" 33 | fi 34 | } 35 | 36 | # Create a PuppetDB uberjar 37 | run lein uberjar 38 | 39 | unset PDBBOX 40 | export PDB_JAR="$(pwd)/target/puppetdb.jar" 41 | 42 | # Run tests 43 | run ext/test/oom-causes-shutdown 44 | run ext/test/top-level-cli 45 | run ext/test/upgrade-and-exit 46 | run ext/test/database-migration-config 47 | run ext/test/schema-mismatch-causes-pdb-shutdown 48 | 49 | # If there are no failures, say so and exit 50 | if test "$failures" -eq 0; then 51 | echo "failures: $failures" 1>&2 52 | exit 0 53 | fi 54 | 55 | # If there are any failures, print them out 56 | # For some reason github's macos TERM=dumb doesn't work with tput: 57 | # tput: No value for $TERM and no -T specified 58 | # though dumb appears to work fine in Linux. 59 | if tput longname 2>/dev/null 1>&2; then 60 | echo "$(tput setaf 1)failures: $failures$(tput sgr 0)" 1>&2 61 | else 62 | echo "failures: $failures" 1>&2 63 | fi 64 | 65 | exit 2 66 | -------------------------------------------------------------------------------- /ext/bin/run-rspec-tests: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Run Ruby rspec tests on Ruby code in puppet/ directory 4 | # Requires single argument, a Puppet version number like 6.27.0 5 | 6 | set -uxeo pipefail 7 | 8 | # Validate argument 9 | test "$#" -eq 1 10 | puppet_ref="$1" 11 | 12 | # Log Ruby version 13 | ruby -v 14 | # Save Puppet version as local test config value 15 | ext/bin/test-config --set puppet-ref "$puppet_ref" 16 | # The puppet directory contains the PuppetDB related Ruby files packaged with 17 | # Puppet as well as the rspec test files that test them 18 | cd puppet 19 | # Install Ruby dependencies from top-level Gemfile via bundle 20 | bundle install --retry=10 21 | # Start rspec tests 22 | bundle exec rspec spec 23 | -------------------------------------------------------------------------------- /ext/bin/sha256sum: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Outputs sha256 checksum of STDIN 4 | # Works on Linux and MacOS 5 | 6 | set -x 7 | echo "$@" 1>&2 8 | 9 | if test "$#" != 0; then 10 | echo "Usage: sha256sum < PATH" 1>&2 11 | exit 2 12 | fi 13 | 14 | case "$OSTYPE" in 15 | darwin*) exec shasum -a 256 "$@" ;; 16 | *) exec sha256sum "$@" ;; 17 | esac 18 | -------------------------------------------------------------------------------- /ext/bin/spec-includes: -------------------------------------------------------------------------------- 1 | """": # -*-python-*- 2 | command -v python3 > /dev/null && exec python3 "$0" "$@" 3 | command -v python2 > /dev/null && exec python2 "$0" "$@" 4 | echo "error: unable to find python3 or python2" 1>&2; exit 2 5 | """ 6 | 7 | # Prints search string if its a component of test spec 8 | # First argument is test spec, second is search string 9 | # Ex: spec-includes core/openjdk8/pg-9.6/rich rich => rich 10 | # Ex: spec-includes core/openjdk8/pg-9.6/rich openjdk8 => openjdk8 11 | # Ex: spec-includes core/openjdk8/pg-9.6/rich foo => 12 | 13 | from __future__ import print_function 14 | from sys import exit, stderr 15 | import os, sys 16 | 17 | def usage(stream): 18 | print('Usage: spec-includes .../pup-5.3.x/srv-5.1.x/something something', 19 | file=stream) 20 | 21 | def misuse(): 22 | usage(stderr) 23 | exit(2) 24 | 25 | len(sys.argv) == 3 or misuse() 26 | specs, what = sys.argv[1:] 27 | specs = specs.split('/') 28 | if what in specs: 29 | print(what) 30 | -------------------------------------------------------------------------------- /ext/bin/symlink-relative-to: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Creates symbolic link to a relative path 4 | # Relative path is forced, even if absolute is given 5 | # Simple on Linux, more complicated on MacOS bc `ln` is missing -r flag 6 | 7 | set -uexo pipefail 8 | 9 | script_name=$(basename "$0") 10 | 11 | target="$1" 12 | link_name="$2" 13 | 14 | case "$OSTYPE" in 15 | darwin*) 16 | # Require coreutils on MacOS 17 | if test -z "$(type -t realpath)"; then 18 | echo "$script_name: realpath missing; please install coreutils" 1>&2 19 | exit 2 20 | fi 21 | # Use realpath to create relative link path 22 | target="$(realpath --relative-to "$(dirname "$link_name")" "$target")" 23 | ln -sf "$target" "$link_name" 24 | ;; 25 | *) 26 | ln -srf "$target" "$link_name" 27 | ;; 28 | esac 29 | -------------------------------------------------------------------------------- /ext/build_defaults.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | project: 'puppetdb' 3 | repo_name: 'puppet8' 4 | nonfinal_repo_name: 'puppet8-nightly' 5 | -------------------------------------------------------------------------------- /ext/jenkins/beaker-tests-source.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "**********************************************" 4 | echo "PARAMS:" 5 | echo "" 6 | echo "sha1: ${sha1}" 7 | echo "GEM_SOURCE: ${GEM_SOURCE}" 8 | echo "REPO_URL: ${REPO_URL}" 9 | echo "**********************************************" 10 | 11 | # Setup RVM and gemset 12 | [[ -s "/usr/local/rvm/scripts/rvm" ]] && source /usr/local/rvm/scripts/rvm 13 | rvm use ruby-2.0.0-p481 14 | 15 | set -e # Fail if we receive non-zero exit code 16 | set -x # Start tracing 17 | set -u # Fail on uninitialized variables 18 | 19 | # beaker params 20 | export BEAKER_COLOR=false 21 | export BEAKER_XML=true 22 | export PUPPETDB_USE_PROXIES=false 23 | export BEAKER_project=PuppetDB 24 | export BEAKER_department=eso-dept 25 | 26 | # Remove old vendor directory to ensure we have a clean slate 27 | if [ -d "vendor" ]; 28 | then 29 | rm -rf vendor 30 | fi 31 | mkdir vendor 32 | 33 | bundle install --path=vendor/bundle --without=test --retry=10 34 | 35 | # Install a copy of leiningen 36 | if [ -d "leiningen" ]; 37 | then 38 | rm -rf leiningen 39 | fi 40 | mkdir leiningen 41 | 42 | wget 'https://raw.githubusercontent.com/technomancy/leiningen/2.5.1/bin/lein' -O leiningen/lein 43 | chmod +x leiningen/lein 44 | 45 | # Now run our tests 46 | PATH=$PATH:$(pwd)/leiningen \ 47 | bundle exec rake beaker:acceptance 48 | -------------------------------------------------------------------------------- /ext/jenkins/beaker-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | echo "**********************************************" 4 | echo "PARAMS FROM UPSTREAM:" 5 | echo "" 6 | echo "PUPPETDB_BRANCH: ${PUPPETDB_BRANCH}" 7 | echo "REF: ${REF}" 8 | echo "GEM_SOURCE: ${GEM_SOURCE}" 9 | echo "SHIP_NIGHTLY: ${SHIP_NIGHTLY}" 10 | echo "REPO_URL: ${REPO_URL}" 11 | echo "PACKAGE_BUILD_VERSION: ${PACKAGE_BUILD_VERSION}" 12 | echo "**********************************************" 13 | 14 | set -x 15 | 16 | # Beaker params 17 | export BEAKER_COLOR=false 18 | export BEAKER_XML=true 19 | export PUPPETDB_INSTALL_TYPE=package 20 | export PUPPETDB_USE_PROXIES=false 21 | export BEAKER_project=PuppetDB 22 | export BEAKER_department=sre-dept 23 | export BEAKER_PRESERVE_HOSTS=onfail 24 | export BEAKER_COLLECT_PERF_DATA=normal 25 | 26 | # Once the necessary PR (puppetlabs/ci-job-configs#2319) has been 27 | # merged, this logic can be removed. 28 | [ "$LAYOUT" = "ec2-west-el7-64mda-el7-64a" ] \ 29 | && LAYOUT=centos7-64mda-64a 30 | [ "$LAYOUT" = "ec2-west-el6-64mda-el6-64a" ] \ 31 | && LAYOUT=centos6-64mda-64a 32 | [ "$LAYOUT" = "ec2-west-ubuntu1204-64mda-64a" ] \ 33 | && LAYOUT=ubuntu1204-64mda-64a 34 | [ "$LAYOUT" = "ec2-west-ubuntu1404-64mda-64a" ] \ 35 | && LAYOUT=ubuntu1404-64mda-64a 36 | [ "$LAYOUT" = "ec2-west-ubuntu1604-64mda-64a" ] \ 37 | && LAYOUT=ubuntu1604-64mda-64a 38 | [ "$LAYOUT" = "ec2-west-debian7-64mda-64a" ] \ 39 | && LAYOUT=debian7-64mda-64a 40 | [ "$LAYOUT" = "ec2-west-el6-64mda-el5-64a-ubuntu1204-64a" ] \ 41 | && LAYOUT=centos6-64mda-centos5-64a-ubuntu1204-64a 42 | [ "$LAYOUT" = "ec2-west-debian7-64mda-fallback" ] \ 43 | && LAYOUT=debian7-64mda-64d 44 | [ "$LAYOUT" = "ec2-west-debian8-64mda-64a" ] \ 45 | && LAYOUT=debian8-64mda-64a 46 | HYPERVISOR="${HYPERVISOR:-vmpooler}" 47 | 48 | export BEAKER_OPTIONS=acceptance/options/${PUPPETDB_DATABASE}.rb 49 | export BEAKER_CONFIG=acceptance/hosts.cfg 50 | bundle exec beaker-hostgenerator $LAYOUT --hypervisor $HYPERVISOR > $BEAKER_CONFIG 51 | 52 | bundle exec rake beaker:acceptance 53 | -------------------------------------------------------------------------------- /ext/jenkins/lein-test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -ueo pipefail 4 | set -x 5 | 6 | ulimit -u 4096 7 | 8 | export PDB_TEST_DUMP_LOG_ON_FAILURE=true 9 | export GEM_SOURCE="https://artifactory.delivery.puppetlabs.net/artifactory/api/gems/rubygems/" 10 | 11 | pghost=fixture-pg94.delivery.puppetlabs.net 12 | pgport=5432 13 | 14 | export HTTP_CLIENT="wget --no-check-certificate -O" 15 | 16 | rm -f testreports.xml *.war *.jar 17 | 18 | export PDB_TEST_DB_HOST="$pghost" 19 | export PDB_TEST_DB_PORT="$pgport" 20 | 21 | # For now, just conflate the normal test and admin users. 22 | export PDB_TEST_DB_USER=pdb_test 23 | export PDB_TEST_DB_ADMIN=pdb_test_admin 24 | export PDB_TEST_DB_USER_PASSWORD=daroniwu54ot 25 | export PDB_TEST_DB_ADMIN_PASSWORD=optuwaeg6ujzo 26 | 27 | PDB_TEST_ID="$(ruby -e "require 'securerandom'; print SecureRandom.uuid")" 28 | PDB_TEST_ID="$(echo -n "$PDB_TEST_ID" | perl -pe 's/[^a-zA-Z0-9_]/_/gmo')" 29 | declare -rx PDB_TEST_ID 30 | 31 | lein --version 32 | lein clean 33 | lein test 34 | 35 | export NO_ACCEPTANCE=true 36 | ext/bin/test-config --reset puppet-ref 37 | PDB_NO_PUPPETSERVER_INSTALL=true ext/bin/test-config --reset puppetserver-ref 38 | exec lein test :integration 39 | -------------------------------------------------------------------------------- /ext/jenkins/terminus-rspec.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | echo "**********************************************" 4 | echo "PARAMS FROM UPSTREAM:" 5 | echo "" 6 | echo "PUPPETDB_BRANCH: ${PUPPETDB_BRANCH}" 7 | echo "GEM_SOURCE: ${GEM_SOURCE}" 8 | echo "SHIP_NIGHTLY: ${SHIP_NIGHTLY}" 9 | echo "REPO_URL: ${REPO_URL}" 10 | echo "**********************************************" 11 | 12 | set -x 13 | 14 | [[ -s "/usr/local/rvm/scripts/rvm" ]] && source "/usr/local/rvm/scripts/rvm" 15 | rvm use $ruby 16 | 17 | # Remove old vendor directory to ensure we have a clean slate 18 | if [ -d "vendor" ]; 19 | then 20 | rm -rf vendor 21 | fi 22 | mkdir vendor 23 | 24 | export GEM_SOURCE="https://artifactory.delivery.puppetlabs.net/artifactory/api/gems/rubygems/" 25 | 26 | NO_ACCEPTANCE=true bundle install --path vendor/bundle --without acceptance 27 | 28 | cd puppet 29 | NO_ACCEPTANCE=true bundle exec rspec spec -fd 30 | -------------------------------------------------------------------------------- /ext/project_data.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | project: 'puppetdb' 3 | author: 'Puppet Labs' 4 | email: 'info@puppetlabs.com' 5 | homepage: 'https://github.com/puppetlabs/puppetdb' 6 | summary: 'Puppet Centralized Storage Daemon' 7 | description: 'Puppet Centralized Storage' 8 | version_file: 'version' 9 | # files and gem_files are space separated lists 10 | files: 'ext *.md puppetb.jar version documentation Rakefile' 11 | tar_excludes: '.gitignore' 12 | gem_files: 13 | gem_require_path: 14 | gem_test_files: 15 | gem_executables: 16 | gem_default_executables: 17 | -------------------------------------------------------------------------------- /ext/test-conf/pgver-default: -------------------------------------------------------------------------------- 1 | 11 2 | -------------------------------------------------------------------------------- /ext/test-conf/puppet-ref-default: -------------------------------------------------------------------------------- 1 | main 2 | -------------------------------------------------------------------------------- /ext/test-conf/puppetserver-ref-default: -------------------------------------------------------------------------------- 1 | main 2 | -------------------------------------------------------------------------------- /ext/test/top-level-cli: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Runs simple tests on PuppetDB jar command line ouptput. 4 | # PuppetDB is started without configuration 5 | # PostgreSQL is not necessary 6 | 7 | set -uexo pipefail 8 | 9 | usage() { echo "Usage: [PDB_JAR=JAR] $(basename "$0")"; } 10 | misuse() { usage 1>&2; exit 2; } 11 | 12 | test $# -eq 0 || misuse 13 | 14 | jdkver=$(ext/bin/jdk-info --print major) 15 | 16 | # Number of characters expected for stderr output for subcommands 17 | expected_help_warnings=0 18 | expected_version_warnings=0 19 | case "$jdkver" in 20 | 8) 21 | # Java 8 deprecation warning 22 | expected_help_warnings=60 23 | expected_version_warnings=60 24 | ;; 25 | 11 | 17) 26 | ;; 27 | *) 28 | echo "JDK version '$jdkver' is not supported" 1>&2 29 | exit 3 30 | ;; 31 | esac 32 | 33 | # Create temporary directory to store output 34 | tmpdir="$(mktemp -d "test-top-level-cli-XXXXXX")" 35 | tmpdir="$(cd "$tmpdir" && pwd)" 36 | trap "$(printf 'rm -rf %q' "$tmpdir")" EXIT 37 | 38 | # Test if unknown command produces correct output and exit status 39 | rc=0 40 | ./pdb frobnicate ... 1>"$tmpdir/out" 2>"$tmpdir/err" || rc=$? 41 | cat "$tmpdir/out" "$tmpdir/err" 42 | test "$rc" -eq 2 43 | grep -F 'Available subcommands:' "$tmpdir/err" 44 | grep -E 'Display version information' "$tmpdir/err" 45 | 46 | # Test if help subcommand produces correct outout 47 | rc=0 48 | ./pdb help 1>"$tmpdir/out" 2>"$tmpdir/err" || rc=$? 49 | cat "$tmpdir/out" "$tmpdir/err" 50 | test "$rc" -eq 0 51 | grep -F 'Available subcommands:' "$tmpdir/out" 52 | grep -F 'Display version information' "$tmpdir/out" 53 | 54 | # Test if number of characters from stderr output matches what is expected 55 | if ! test $(wc -c < "$tmpdir/err") -eq "$expected_help_warnings"; then 56 | echo 'ERROR: Unpected help warnings:' 1>&2 57 | cat "$tmpdir/err" 58 | false 59 | fi 60 | 61 | # Test if version subcommand produces correct output 62 | rc=0 63 | ./pdb version 1>"$tmpdir/out" 2>"$tmpdir/err" || rc=$? 64 | cat "$tmpdir/out" "$tmpdir/err" 65 | test "$rc" -eq 0 66 | grep -E '^version=' "$tmpdir/out" 67 | grep -E '^target_schema_version=' "$tmpdir/out" 68 | test $(wc -c < "$tmpdir/err") -eq $expected_version_warnings 69 | -------------------------------------------------------------------------------- /locales/eo.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR Puppet 3 | # This file is distributed under the same license as the puppetlabs.puppetdb package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: puppetlabs.puppetdb\n" 9 | "Report-Msgid-Bugs-To: docs@puppet.com\n" 10 | "POT-Creation-Date: \n" 11 | "PO-Revision-Date: 2017-03-22 14:56-0600\n" 12 | "Language-Team: \n" 13 | "MIME-Version: 1.0\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Content-Transfer-Encoding: 8bit\n" 16 | "X-Generator: Poedit 1.8.12\n" 17 | "Last-Translator: \n" 18 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 19 | "Language: eo\n" 20 | 21 | -------------------------------------------------------------------------------- /locust/load-test/cd4pe.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - path: "/pdb/query/v4/resources" 3 | method: POST 4 | headers: {content-type: application/json} 5 | query: ["extract",["parameters"],["and",["=","title","Puppet_enterprise::Master::Code_manager"]]] 6 | alias: CD4PE - code manager resource 7 | - path: "/pdb/query/v4/resources" 8 | method: POST 9 | headers: {content-type: application/json} 10 | query: ["extract",["title","type","resource","file","certname","line","environment"],["and",["or",["and",["null?","file",false],["or",["~","file","impact_analysis_tests_prod/site/profile/manifests/nested.pp"],["~","file","impact_analysis_tests_prod/site/profile/manifests/nested/includes.pp"]]],["=","title","Profile::Nested"],["=","title","Profile::Nested::Includes"]],["=","environment","impact_analysis_tests_prod"]]] 11 | alias: CD4PE - impact analysis 1 12 | - path: "/pdb/query/v4/resources" 13 | method: POST 14 | headers: {content-type: application/json} 15 | query: ["extract",["title","type","resource","file","certname","line","environment"],["and",["or",["and",["null?","file",false],["or",["~","file","impact_analysis_tests_prod/site/role/manifests/example2.pp"]]],["=","title","Role::Example2"]],["=","environment","impact_analysis_tests_prod"]]] 16 | alias: CD4PE - impact analysis 2 17 | - path: "/pdb/query/v4/resources" 18 | method: POST 19 | headers: {content-type: application/json} 20 | query: ["extract",["title","type","resource","file","certname","line","environment"],["and",["or",["and",["null?","file",false],["or",["~","file","impact_analysis_tests_prod/modules/cd4pe"],["~","file","impact_analysis_tests_prod/modules/cd4pe_tests"],["~","file","impact_analysis_tests_prod/manifests/site.pp"],["~","file","impact_analysis_tests_prod/site/profile/manifests/base.pp"],["~","file","impact_analysis_tests_prod/site/profile/manifests/firewall.pp"],["~","file","impact_analysis_tests_prod/site/role/manifests/example.pp"],["~","file","impact_analysis_tests_prod/site/role/manifests/webserver.pp"]]],["=","title","Impact_analysis_tests_prod::Site"],["=","title","Profile::Base"],["=","title","Profile::Firewall"],["=","title","Role::Example"],["=","title","Role::Webserver"]],["=","environment","impact_analysis_tests_prod"]]] 21 | alias: CD4PE - firewall analysis cd4pe 22 | -------------------------------------------------------------------------------- /locust/load-test/example.yaml: -------------------------------------------------------------------------------- 1 | # Example 2 | # name: my custom call name, will be shown in the report 3 | # path: path without the host. The host is set in cli as an option 4 | # query: query should be hash for POST and string for GET 5 | # method: GET/POST 6 | # headers: any custom headers that will be sent with the request 7 | --- 8 | - path: "/pdb/query/v4/facts" 9 | limit: 100 10 | offset: 1 11 | method: GET 12 | headers: '' 13 | - path: "/pdb/query/v4/facts" 14 | query: ["~", "certname", "host"] 15 | method: POST 16 | headers: {content-type: application/json} 17 | alias: example 2 18 | -------------------------------------------------------------------------------- /locust/run-load-test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys, subprocess, os 4 | from datetime import datetime 5 | 6 | def usage(): 7 | usage = """ 8 | This script only adds defaults if there are no options 9 | Usage: run-load-test [options] 10 | 11 | Defaults: 12 | -H [--host] http://localhost:8080 13 | -u [--users] 1 14 | -s [--spawn_rate] 1 15 | -t [--run_time] 1m 16 | -f [--locustfile] locust/load-test/load-test.py 17 | -T [--tags] example 18 | -c [--csv] 19 | --html .html 20 | """ 21 | print(usage) 22 | 23 | def add_default_args(program_args): 24 | defaults = [['--headless'], ['-H', 'http://localhost:8080'], 25 | ["-u", '1'], ["-r", '1'], ["-t", '1m'], ['-f', locust_filepath], 26 | ['--html', f'{timestamp}.html'], ['--tags', 'example'], ['--csv', timestamp]] 27 | additional_args = [] 28 | for default_arg in defaults: 29 | found = False 30 | for arg in program_args: 31 | if arg == default_arg[0]: 32 | found = True 33 | if not found: 34 | additional_args += default_arg 35 | 36 | return additional_args + program_args 37 | 38 | subprocess.run([sys.executable, "-m", "pip", "install", "locust", "pyyaml", "-U"]) 39 | 40 | missing_defaults = [] 41 | dir_path = os.path.dirname(os.path.realpath(__file__)) 42 | workdir = os.getcwd() 43 | locust_filepath = os.path.join(dir_path, 'load-test', 'load-test.py') 44 | timestamp = datetime.now().strftime("%d-%m-%YT%H:%M:%S") 45 | 46 | sys_args = sys.argv[1:] 47 | if '--help' in sys_args: 48 | subprocess.run(["locust", "--help"]) 49 | usage() 50 | exit() 51 | 52 | locust_args = add_default_args(sys_args) 53 | subprocess.run(["locust"] + locust_args) 54 | -------------------------------------------------------------------------------- /puppet/lib/puppet/face/node/deactivate.rb: -------------------------------------------------------------------------------- 1 | require 'puppet/util/puppetdb' 2 | require 'puppet/util/puppetdb/command_names' 3 | 4 | Puppet::Face.define(:node, '0.0.1') do 5 | 6 | CommandDeactivateNode = Puppet::Util::Puppetdb::CommandNames::CommandDeactivateNode 7 | 8 | action :deactivate do 9 | summary "Deactivate a set of nodes in PuppetDB" 10 | arguments " [ ...]" 11 | description <<-DESC 12 | This will issue '#{CommandDeactivateNode}' commands to the PuppetDB server for 13 | each node specified. The server is found by looking in 14 | $confdir/puppetdb.conf. If any command submissions fail, the process will 15 | be aborted. 16 | DESC 17 | 18 | when_invoked do |*args| 19 | 20 | opts = args.pop 21 | raise ArgumentError, "Please provide at least one node for deactivation" if args.empty? 22 | 23 | Puppet::Node.indirection.terminus_class = :puppetdb 24 | Puppet::Node.indirection.cache_class = nil 25 | 26 | args.inject({}) do |results,node| 27 | results.merge node => Puppet::Node.indirection.destroy(node)['uuid'] 28 | end 29 | end 30 | 31 | when_rendering(:console) do |value| 32 | value.map do |node,uuid| 33 | "Submitted '#{CommandDeactivateNode}' for #{node} with UUID #{uuid}" 34 | end.join("\n") 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /puppet/lib/puppet/functions/puppetdb_query.rb: -------------------------------------------------------------------------------- 1 | require 'puppet/util/puppetdb' 2 | Puppet::Functions.create_function(:puppetdb_query) do 3 | dispatch :puppetdb_query do 4 | required_param 'Variant[String[1], Array[Data, 1]]', :query 5 | end 6 | 7 | def puppetdb_query(query) 8 | Puppet::Util::Puppetdb.query_puppetdb(query) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /puppet/lib/puppet/indirector/facts/puppetdb_apply.rb: -------------------------------------------------------------------------------- 1 | require 'puppet/indirector/facts/puppetdb' 2 | 3 | # This class provides an alternative implementation of the Facts::Puppetdb 4 | # terminus that better suits execution via `puppet apply`. 5 | # 6 | # This terminus is designed to be used as a cache terminus, to ensure that facts 7 | # are stored in PuppetDB. It does not act as a real cache itself however, it 8 | # tells Puppet to fallback to the `terminus` instead. 9 | class Puppet::Node::Facts::PuppetdbApply < Puppet::Node::Facts::Puppetdb 10 | attr_writer :dbstored 11 | 12 | # Here we override the normal save, only saving the first time, as a `save` 13 | # can be called multiple times in a puppet run. 14 | def save(args) 15 | unless @dbstored 16 | @dbstored = true 17 | super(args) 18 | end 19 | end 20 | 21 | # By returning nil, we force puppet to use the real terminus. 22 | def find(args) 23 | nil 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /puppet/lib/puppet/indirector/node/puppetdb.rb: -------------------------------------------------------------------------------- 1 | require 'puppet/node' 2 | require 'puppet/indirector/rest' 3 | require 'puppet/util/puppetdb' 4 | 5 | class Puppet::Node::Puppetdb < Puppet::Indirector::REST 6 | include Puppet::Util::Puppetdb 7 | 8 | def find(request) 9 | end 10 | 11 | def save(request) 12 | end 13 | 14 | def destroy(request) 15 | current_time = Time.now 16 | 17 | submit_command(request.key, CommandDeactivateNode, 3, current_time.clone.utc) do 18 | {:certname => request.key, 19 | :producer_timestamp => Puppet::Util::Puppetdb.to_wire_time(current_time)} 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /puppet/lib/puppet/util/puppetdb/atom.rb: -------------------------------------------------------------------------------- 1 | require 'thread' 2 | 3 | module Puppet::Util::Puppetdb 4 | class Atom 5 | def initialize(value) 6 | @value = value 7 | @mutex = Mutex.new 8 | end 9 | 10 | def deref() 11 | @mutex.synchronize { 12 | @value 13 | } 14 | end 15 | 16 | def reset(value) 17 | @mutex.synchronize { 18 | @value = value 19 | } 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /puppet/lib/puppet/util/puppetdb/command_names.rb: -------------------------------------------------------------------------------- 1 | module Puppet::Util::Puppetdb 2 | module CommandNames 3 | CommandReplaceCatalog = "replace catalog" 4 | CommandReplaceFacts = "replace facts" 5 | CommandDeactivateNode = "deactivate node" 6 | CommandStoreReport = "store report" 7 | CommandReplaceCatalogInputs = "replace catalog inputs" 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /puppet/spec/README.markdown: -------------------------------------------------------------------------------- 1 | NOTE 2 | ==== 3 | 4 | This project's specs depend on puppet core, and thus they require the 5 | puppetlabs_spec_helper project. For more information please see the 6 | README in that project, which can be found here: 7 | 8 | https://github.com/puppetlabs/puppetlabs_spec_helper -------------------------------------------------------------------------------- /puppet/spec/spec.opts: -------------------------------------------------------------------------------- 1 | --format 2 | s 3 | --colour 4 | --loadby 5 | mtime 6 | --backtrace 7 | -------------------------------------------------------------------------------- /puppet/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | dir = File.expand_path(File.dirname(__FILE__)) 2 | $LOAD_PATH.unshift File.join(dir, "../lib") 3 | # Maybe puppetlabs_spec_helper is in a directory next to puppetdb. If not, we 4 | # don't fail any worse than we already would. 5 | $LOAD_PATH.push File.join(dir, "../../../puppetlabs_spec_helper") 6 | 7 | require 'cgi' 8 | require 'rspec' 9 | require 'rspec/expectations' 10 | require 'puppetlabs_spec_helper/puppet_spec_helper' 11 | require 'tmpdir' 12 | require 'fileutils' 13 | require 'puppet' 14 | require 'puppet/util/puppetdb' 15 | require 'puppet/util/log' 16 | 17 | 18 | def create_environmentdir(environment) 19 | envdir = File.join(Puppet[:environmentpath], environment) 20 | if not Dir.exist?(envdir) 21 | Dir.mkdir(envdir) 22 | end 23 | end 24 | 25 | def extract_producer_timestamp(command) 26 | DateTime.parse(command["producer_timestamp"]).to_time.to_i 27 | end 28 | 29 | def assert_command_req(expected_payload, actual_payload) 30 | req = JSON.parse(actual_payload) 31 | actual_producer_timestamp = extract_producer_timestamp(req) 32 | req.delete("producer_timestamp") 33 | req == expected_payload && 34 | actual_producer_timestamp <= Time.now.to_i 35 | end 36 | 37 | def assert_valid_producer_ts(path) 38 | _, param_str = path.split "?" 39 | params = CGI::parse(param_str) 40 | return false if params["producer-timestamp"].size != 1 41 | Time.iso8601(params["producer-timestamp"].first) 42 | end 43 | 44 | def create_http_response(url, nethttp) 45 | if Puppet::PUPPETVERSION.to_f < 7 46 | Puppet::HTTP::Response.new(nethttp, url) 47 | else 48 | Puppet::HTTP::ResponseNetHTTP.new(url, nethttp) 49 | end 50 | end 51 | 52 | RSpec.configure do |config| 53 | 54 | config.before :each do 55 | @logs = [] 56 | Puppet::Util::Log.level = :info 57 | Puppet::Util::Log.newdestination(Puppet::Test::LogCollector.new(@logs)) 58 | 59 | def test_logs 60 | @logs.map(&:message) 61 | end 62 | 63 | end 64 | 65 | config.expect_with :rspec do |c| 66 | c.syntax = [:should, :expect] 67 | end 68 | 69 | end 70 | -------------------------------------------------------------------------------- /puppet/spec/unit/face/node/deactivate_spec.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'spec_helper' 4 | require 'puppet/face' 5 | require 'puppet/indirector/node/puppetdb' 6 | 7 | describe "node face: deactivate" do 8 | let(:subject) { Puppet::Face[:node, :current] } 9 | 10 | it "should fail if no node is given" do 11 | expect { subject.deactivate }.to raise_error ArgumentError, /provide at least one node/ 12 | end 13 | 14 | it "should deactivate each node using the puppetdb terminus" do 15 | nodes = ['a', 'b', 'c'] 16 | nodes.each do |node| 17 | Puppet::Node::Puppetdb.any_instance.expects(:destroy).with do |request| 18 | request.key == node 19 | end.returns('uuid' => "uuid_#{node}") 20 | end 21 | 22 | subject.deactivate(*nodes).should == { 23 | 'a' => 'uuid_a', 24 | 'b' => 'uuid_b', 25 | 'c' => 'uuid_c', 26 | } 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /puppet/spec/unit/face/node/status_spec.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'spec_helper' 4 | require 'puppet' 5 | require 'puppet/face' 6 | require 'puppet/network/http_pool' 7 | 8 | describe "node face: status" do 9 | let(:subject) { Puppet::Face[:node, :current] } 10 | let(:headers) do 11 | { 12 | "Accept" => "application/json", 13 | "Content-Type" => "application/x-www-form-urlencoded; charset=UTF-8", 14 | } 15 | end 16 | 17 | it "should fail if no node is given" do 18 | expect { subject.status }.to raise_error ArgumentError, /provide at least one node/ 19 | end 20 | 21 | it "should fetch the status of each node" do 22 | http = stub 'http' 23 | Puppet::HTTP::Client.stubs(:new).returns(http) 24 | 25 | nodes = %w[a b c d e] 26 | nodes.each do |node| 27 | http.expects(:get).with do |uri, opts| 28 | headers == opts[:headers] && 29 | uri.path == "/pdb/query/v4/nodes/#{node}" 30 | end 31 | end 32 | 33 | subject.status(*nodes) 34 | end 35 | 36 | it "should CGI escape the node names" do 37 | http = stub 'http' 38 | Puppet::HTTP::Client.stubs(:new).returns(http) 39 | 40 | node = "foo/+*&bar" 41 | 42 | http.expects(:get).with do |uri, opts| 43 | headers == opts[:headers] && 44 | uri.path == "/pdb/query/v4/nodes/foo%2F%2B%2A%26bar" 45 | end 46 | 47 | subject.status(node) 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /puppet/spec/unit/indirector/facts/puppetdb_apply_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'puppet/indirector/facts/puppetdb_apply' 3 | 4 | describe Puppet::Node::Facts::PuppetdbApply do 5 | describe "#save" do 6 | let(:facts) { Puppet::Node::Facts.new('foo') } 7 | 8 | def save 9 | subject.save(Puppet::Node::Facts.indirection.request(:save, facts.name, facts)) 10 | end 11 | 12 | it "should only submit commands once" do 13 | subject.expects(:submit_command).once 14 | save 15 | save 16 | save 17 | end 18 | 19 | end 20 | 21 | describe "#find" do 22 | it "always returns nil to force the cache to be skipped" do 23 | subject.find('foo').should be_nil 24 | end 25 | end 26 | 27 | end 28 | -------------------------------------------------------------------------------- /puppet/spec/unit/indirector/node/puppetdb_spec.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rspec 2 | 3 | require 'spec_helper' 4 | 5 | require 'puppet/indirector/node/puppetdb' 6 | require 'puppet/util/puppetdb/command_names' 7 | require 'json' 8 | require 'date' 9 | require 'time' 10 | 11 | describe Puppet::Node::Puppetdb do 12 | 13 | before :each do 14 | Puppet::Node.indirection.stubs(:terminus).returns(subject) 15 | end 16 | 17 | let(:node) { "something.example.com" } 18 | let(:producer_timestamp) { Puppet::Util::Puppetdb.to_wire_time(Time.now) } 19 | 20 | def destroy 21 | Puppet::Node.indirection.destroy(node) 22 | end 23 | 24 | describe "#destroy" do 25 | let(:nethttpok) { Net::HTTPOK.new('1.1', 200, 'OK') } 26 | let(:responseok) { create_http_response("mock url", nethttpok) } 27 | let(:http) { mock 'http' } 28 | before :each do 29 | Puppet::HTTP::Client.expects(:new).returns http 30 | end 31 | 32 | it "should POST a '#{Puppet::Util::Puppetdb::CommandNames::CommandDeactivateNode}' command" do 33 | responseok.stubs(:body).returns '{"uuid": "a UUID"}' 34 | http.expects(:post).with do |uri,body,headers| 35 | req = JSON.parse(body) 36 | req["certname"] == node && 37 | extract_producer_timestamp(req) <= Time.now.to_i 38 | end.returns responseok 39 | 40 | destroy 41 | end 42 | 43 | it "should log a deprecation warning if one is returned from PuppetDB" do 44 | nethttpok['x-deprecation'] = 'A horrible deprecation warning!' 45 | responseok.stubs(:body).returns '{"uuid": "a UUID"}' 46 | 47 | Puppet.expects(:deprecation_warning).with do |msg| 48 | msg =~ /A horrible deprecation warning!/ 49 | end 50 | 51 | http.stubs(:post).returns responseok 52 | 53 | destroy 54 | end 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /puppet/spec/unit/util/puppetdb_spec.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rspec 2 | # encoding: UTF-8 3 | 4 | require 'spec_helper' 5 | require 'digest/sha1' 6 | require 'puppet/util/puppetdb' 7 | require 'puppet/util/puppetdb/command_names' 8 | require 'puppet/util/puppetdb/http' 9 | require 'json' 10 | 11 | 12 | class FakeHttpResponse 13 | def initialize(body) 14 | @body = body 15 | end 16 | attr_reader :body 17 | end 18 | 19 | describe Puppet::Util::Puppetdb do 20 | subject { Object.new.extend described_class } 21 | 22 | describe "#submit_command" do 23 | let(:payload) { {'resistance' => 'futile', 'opinion' => 'irrelevant'} } 24 | let(:command1) { Puppet::Util::Puppetdb::Command.new("OPEN SESAME", 1, 'foo.localdomain', Time.now.utc, 25 | payload.merge(:uniqueprop => "command1")) } 26 | 27 | it "should submit the command" do 28 | # careful here... since we're going to stub Command.new, we need to 29 | # make sure we reference command1 first, because it calls Command.new. 30 | command1.expects(:submit).once 31 | Puppet::Util::Puppetdb::Command.expects(:new).once.returns(command1) 32 | subject.submit_command(command1.certname, 33 | command1.command, 34 | command1.producer_timestamp_utc, 35 | command1.version) { command1.payload } 36 | end 37 | 38 | end 39 | 40 | describe ".query_puppetdb" do 41 | let(:response) { JSON.generate({'certname' => 'futile', 'status' => 'irrelevant'}) } 42 | let(:query) { ["=", "type", "Foo"] } 43 | let(:http_response) { FakeHttpResponse.new(response) } 44 | it "should query PuppetDB" do 45 | # careful here... since we're going to stub Command.new, we need to 46 | # make sure we reference command1 first, because it calls Command.new. 47 | Puppet::Util::Puppetdb::Http.expects(:action).once.returns(http_response) 48 | Puppet::Util::Puppetdb.query_puppetdb(query) 49 | end 50 | 51 | end 52 | 53 | end 54 | -------------------------------------------------------------------------------- /resources/ext/cli/anonymize: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ${JAVA_BIN} ${JAVA_ARGS} -cp ${INSTALL_DIR}/puppetdb.jar clojure.main -m puppetlabs.puppetdb.core anonymize "$@" 4 | -------------------------------------------------------------------------------- /resources/ext/cli/upgrade: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # Note: the variables here may look generic, but are currently 6 | # exported by the puppet packaging scripts. For example, even though 7 | # they may look like it, JAVA_BIN and JAVA_ARGS are not upstream java 8 | # variables (like JAVA_OPTS), but are set and exported by puppet. And 9 | # the USER variable here is not the bash variable of the same name, 10 | # but is shadowing/clobbering it. Most/all of these should be renamed 11 | # to something less generic like PDB_CONFIG_FILE, or better yet (for 12 | # that particular one), perhaps puppetdb should just support the 13 | # variable itself. 14 | 15 | cli_defaults=${INSTALL_DIR}/cli/cli-defaults.sh 16 | CLASSPATH=${INSTALL_DIR}/puppetdb.jar 17 | 18 | if [ -e "$cli_defaults" ]; then 19 | . "$cli_defaults" 20 | if [ $? -ne 0 ]; then 21 | echo "Unable to initialize cli defaults, failing start." 1>&2 22 | exit 1 23 | fi 24 | fi 25 | 26 | cmd=($(printf "%q %s -Dlogappender=STDOUT -cp %q clojure.main -m puppetlabs.puppetdb.core upgrade -c %q" \ 27 | "$JAVA_BIN" "$JAVA_ARGS" "$CLASSPATH" "$CONFIG")) 28 | 29 | if test "$(id -un)" = "$USER"; then 30 | exec "${cmd[@]}" "$@" 31 | else 32 | exec su "$USER" -s /bin/sh -c "${cmd[*]} ${*}" 33 | fi 34 | -------------------------------------------------------------------------------- /resources/ext/config/bootstrap.cfg: -------------------------------------------------------------------------------- 1 | ../../puppetlabs/puppetdb/bootstrap.cfg -------------------------------------------------------------------------------- /resources/ext/config/conf.d/auth.conf: -------------------------------------------------------------------------------- 1 | authorization: { 2 | version: 1 3 | rules: [ 4 | { 5 | # Allow unauthenticated access to the status service endpoint 6 | match-request: { 7 | path: "/status/v1/services" 8 | type: path 9 | method: get 10 | } 11 | allow-unauthenticated: true 12 | sort-order: 500 13 | name: "puppetlabs status service - full" 14 | }, 15 | { 16 | match-request: { 17 | path: "/status/v1/simple" 18 | type: path 19 | method: get 20 | } 21 | allow-unauthenticated: true 22 | sort-order: 500 23 | name: "puppetlabs status service - simple" 24 | }, 25 | { 26 | # Allow nodes to access the metrics service 27 | # for puppetdb, the metrics service is the only 28 | # service using the authentication service 29 | match-request: { 30 | path: "/metrics" 31 | type: path 32 | method: [get, post] 33 | } 34 | allow: "*" 35 | sort-order: 500 36 | name: "puppetlabs puppetdb metrics" 37 | }, 38 | { 39 | # Deny everything else. This ACL is not strictly 40 | # necessary, but illustrates the default policy 41 | match-request: { 42 | path: "/" 43 | type: path 44 | } 45 | deny: "*" 46 | sort-order: 999 47 | name: "puppetlabs deny all" 48 | } 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /resources/ext/config/conf.d/config.ini: -------------------------------------------------------------------------------- 1 | # See README.md for more thorough explanations of each section and 2 | # option. 3 | 4 | [global] 5 | # Store mq/db data in a custom directory 6 | vardir = /opt/puppetlabs/server/data/puppetdb 7 | 8 | # Use an external logback config file 9 | logging-config = /etc/puppetlabs/puppetdb/logback.xml 10 | 11 | [command-processing] 12 | # How many command-processing threads to use, defaults to (CPUs / 2) 13 | # threads = 4 14 | 15 | # How many threads can write to disk at once, defaults to min(CPUs / 2, 4) 16 | # concurrent-writes = 4 17 | -------------------------------------------------------------------------------- /resources/ext/config/conf.d/database.ini: -------------------------------------------------------------------------------- 1 | [database] 2 | 3 | # The database address, i.e. //HOST:PORT/DATABASE_NAME 4 | # subname = //localhost:5432/puppetdb 5 | 6 | # Connect as a specific user 7 | # username = foobar 8 | 9 | # Use a specific password 10 | # password = foobar 11 | 12 | # How often (in minutes) to compact the database 13 | # gc-interval = 60 14 | -------------------------------------------------------------------------------- /resources/ext/config/conf.d/jetty.ini: -------------------------------------------------------------------------------- 1 | [jetty] 2 | # IP address or hostname to listen for clear-text HTTP. To avoid resolution 3 | # issues, IP addresses are recommended over hostnames. 4 | # Default is `localhost`. 5 | # host = 6 | 7 | # Port to listen on for clear-text HTTP. 8 | port = 8080 9 | 10 | # The following are SSL specific settings. They can be configured 11 | # automatically with the tool `puppetdb ssl-setup`, which is normally 12 | # ran during package installation. 13 | 14 | # IP address to listen on for HTTPS connections. Hostnames can also be used 15 | # but are not recommended to avoid DNS resolution issues. To listen on all 16 | # interfaces, use `0.0.0.0`. 17 | # ssl-host = 18 | 19 | # The port to listen on for HTTPS connections 20 | # ssl-port = 21 | 22 | # Private key path 23 | # ssl-key = 24 | 25 | # Public certificate path 26 | # ssl-cert = 27 | 28 | # Certificate authority path 29 | # ssl-ca-cert = 30 | 31 | # Access logging configuration path. To turn off access logging 32 | # comment out the line with `access-log-config=...` 33 | access-log-config = /etc/puppetlabs/puppetdb/request-logging.xml 34 | -------------------------------------------------------------------------------- /resources/ext/config/conf.d/repl.ini: -------------------------------------------------------------------------------- 1 | [nrepl] 2 | # Set to true to enable the remote REPL 3 | enabled = false 4 | 5 | # What port the REPL should listen on 6 | port = 8082 7 | 8 | # IP address to listen on 9 | host = 127.0.0.1 10 | -------------------------------------------------------------------------------- /resources/ext/config/request-logging.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | /var/log/puppetlabs/puppetdb/puppetdb-access.log 4 | true 5 | 6 | /var/log/puppetlabs/puppetdb/puppetdb-access-%d{yyyy-MM-dd}.%i.log.gz 7 | 8 | 200MB 9 | 90 10 | 1GB 11 | 12 | 13 | %h %l %u [%t] "%r" %s %b "%i{Referer}" "%i{User-Agent}" %D %header{X-Uncompressed-Length} 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /resources/ext/docs: -------------------------------------------------------------------------------- 1 | ../../documentation -------------------------------------------------------------------------------- /resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d %-5p [%thread] [%c{2}] %m%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /resources/puppetlabs/puppetdb/benchmark/config.ini: -------------------------------------------------------------------------------- 1 | [global] 2 | logging-config = resources/logback.xml 3 | 4 | [jetty] 5 | host = 0.0.0.0 6 | port = 8080 7 | -------------------------------------------------------------------------------- /resources/puppetlabs/puppetdb/bootstrap.cfg: -------------------------------------------------------------------------------- 1 | # This file is used by the application framework (trapperkeeper) to 2 | # determine what services should be loaded at boot time. 3 | # For more info, see: 4 | # https://github.com/puppetlabs/trapperkeeper/wiki/Bootstrapping 5 | 6 | # Web Server 7 | puppetlabs.trapperkeeper.services.webserver.jetty10-service/jetty10-service 8 | 9 | # Webrouting 10 | puppetlabs.trapperkeeper.services.webrouting.webrouting-service/webrouting-service 11 | 12 | # TK metrics - the authorization service is currently only used by the metrics service 13 | puppetlabs.trapperkeeper.services.authorization.authorization-service/authorization-service 14 | puppetlabs.trapperkeeper.services.metrics.metrics-service/metrics-webservice 15 | # TK status 16 | puppetlabs.trapperkeeper.services.status.status-service/status-service 17 | puppetlabs.trapperkeeper.services.scheduler.scheduler-service/scheduler-service 18 | 19 | # PuppetDB Services 20 | puppetlabs.puppetdb.cli.services/puppetdb-service 21 | puppetlabs.puppetdb.command/command-service 22 | puppetlabs.puppetdb.pdb-routing/maint-mode-service 23 | puppetlabs.puppetdb.pdb-routing/pdb-routing-service 24 | puppetlabs.puppetdb.config/config-service 25 | 26 | # NREPL 27 | puppetlabs.trapperkeeper.services.nrepl.nrepl-service/nrepl-service 28 | 29 | # Dashboard redirect for "/" (not "/pdb"): remove to disable 30 | puppetlabs.puppetdb.dashboard/dashboard-redirect-service 31 | -------------------------------------------------------------------------------- /resources/puppetlabs/puppetdb/generate/realistic/README.md: -------------------------------------------------------------------------------- 1 | # Generated data 2 | 3 | This data is a best guess at what a realistic size/shape of data might be in 4 | PuppetDB to allow us to do more accurate performance testing. It was generated 5 | using the configuration values found in `metadata.txt`. 6 | -------------------------------------------------------------------------------- /resources/puppetlabs/puppetdb/generate/realistic/metadata.txt: -------------------------------------------------------------------------------- 1 | {:generated-from 2 | {:resource-size 500, 3 | :num-additional-logs 10, 4 | :num-reports 20, 5 | :silent false, 6 | :max-fact-depth 7, 7 | :additional-edge-percent 15, 8 | :random-distribution false, 9 | :exclude-unchanged-resources true, 10 | :high-change-reports-percent 5.0, 11 | :verbose false, 12 | :percent-add-report-logs 20, 13 | :high-change-resources-percent 60, 14 | :num-hosts 5, 15 | :blob-count 2, 16 | :total-fact-size 15, 17 | :low-change-resources-percent 5, 18 | :num-facts 400, 19 | :help false, 20 | :blob-size 40, 21 | :num-resources 800, 22 | :num-classes 100, 23 | :num-packages 1000, 24 | :title-size 40, 25 | :low-change-reports-percent 15.0}, 26 | :stored-at "/tmp/pdb-generate-14340763794995129976"} 27 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb) 2 | 3 | ;;; Notable namespace keys 4 | 5 | ;; :puppetlabs.puppetdb.known-error? - indicates that the error is 6 | ;; expected, e.g. a query or command syntax error, JSON parse error, 7 | ;; configuration error, etc. In general, the stack trace should be 8 | ;; considered uninteresting (i.e. only the message is expected to be 9 | ;; interesting), but if there's a cause (.getCause) or suppressed 10 | ;; exceptions (.getSuppressed) then they may also be interesting (in 11 | ;; their entirety). A cause should only be added intentionally (when 12 | ;; constructing the ex-info), but suppressed exceptions may be added 13 | ;; indirectly, while unwinding, via for example java's 14 | ;; try-with-resources or murphy. 15 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/cli/tk_util.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.cli.tk-util 2 | "This namespace is separate from cli.util because we don't want to 3 | require any more than we have to there." 4 | (:require 5 | [clojure.tools.logging :as log] 6 | [puppetlabs.i18n.core :refer [trs]] 7 | [puppetlabs.puppetdb.cli.util :as cliu])) 8 | 9 | (defn run-tk-cli-cmd [f] 10 | (let [jdk (cliu/java-version)] 11 | (if-let [{:keys [warn error]} (cliu/jdk-unsupported-msg jdk)] 12 | (if error 13 | (do 14 | (binding [*out* *err*] (println (trs "error:") error)) 15 | (log/error error) 16 | cliu/err-exit-status) 17 | (do 18 | (binding [*out* *err*] (println (trs "warn:") warn)) 19 | (log/warn warn) 20 | (f))) 21 | (f)))) 22 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/cli/util.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.cli.util 2 | "As this namespace is required by both the tk and non-tk subcommands, 3 | it must remain very lightweight, so that subcommands like 4 | \"version\" aren't slowed down by loading the entire logging 5 | subsystem or trapperkeeper, etc." 6 | (:require 7 | [puppetlabs.i18n.core :refer [trs]])) 8 | 9 | (def err-exit-status 2) 10 | 11 | ;; FIXME: maybe change this to rely on java.lang.Runtime$Version for 12 | ;; jdk > 8 (cf. pdb-jdk-ver in project.clj). 13 | 14 | ;; Testing hook 15 | (defn java-version [] (System/getProperty "java.version")) 16 | 17 | (def supported-java-version "17") 18 | 19 | (defn jdk-support-status 20 | "Returns :official, :tested, :deprecated, :unknown, or :no." 21 | [version] 22 | (cond 23 | (re-matches #"1\.[1234567]($|(\..*))" version) :no 24 | (re-matches #"1\.[89]($|(\..*))" version) :deprecated 25 | (re-matches #"10($|(\..*))" version) :deprecated 26 | (re-matches (re-pattern (str supported-java-version "($|(\\..*))")) version) :official 27 | (re-matches #"11($|(\..*))" version) :tested 28 | :else :unknown)) 29 | 30 | (defn jdk-unsupported-msg [version] 31 | (let [status (jdk-support-status version)] 32 | (case status 33 | (:unknown) {:warn (trs "JDK {0} is neither tested nor supported. Please use JDK {1}" version supported-java-version)} 34 | (:deprecated) {:warn (trs "JDK {0} is deprecated, please upgrade to JDK {1}" version supported-java-version)} 35 | (:official :tested) nil 36 | {:error (trs "PuppetDB doesn''t support JDK {0}" version)}))) 37 | 38 | (defn run-cli-cmd [f] 39 | (let [jdk (java-version)] 40 | (if-let [{:keys [warn error]} (jdk-unsupported-msg jdk)] 41 | (if error 42 | (do 43 | (binding [*out* *err*] (println (trs "error:") error)) 44 | err-exit-status) 45 | (do 46 | (binding [*out* *err*] (println (trs "warn:") warn)) 47 | (f))) 48 | (f)))) 49 | 50 | (defn exit [status] 51 | (shutdown-agents) 52 | (binding [*out* *err*] (flush)) 53 | (flush) 54 | (System/exit status)) 55 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/cli/version.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.cli.version 2 | "Version utility 3 | 4 | This simple command-line tool prints a list of info about 5 | the version of PuppetDB. It is useful for testing and other situations 6 | where you'd like to know some of the version details without having 7 | a running instance of PuppetDB. 8 | 9 | The output is currently formatted like the contents of a java properties file; 10 | each line contains a single property name, followed by an equals sign, followed 11 | by the property value." 12 | (:require 13 | [puppetlabs.puppetdb.cli.util :refer [exit run-cli-cmd]] 14 | [puppetlabs.puppetdb.meta.version :refer [version]] 15 | [puppetlabs.puppetdb.scf.migrate :refer [desired-schema-version]])) 16 | 17 | ;; TODO: Would like to add database info and some other things here, but that 18 | ;; will require us to have access to the configuration info. At present, the 19 | ;; configuration parsing code is scattered throughout services.clj and not 20 | ;; cleanly accessible from here. Perhaps we can revisit this once we've 21 | ;; refactored and cleaned up the configuration stuff a bit. 22 | 23 | (defn show-version [_args] 24 | (doseq [[key val] {"version" (version) 25 | "target_schema_version" (desired-schema-version)}] 26 | (println (format "%s=%s" key val)))) 27 | 28 | (defn cli 29 | "Runs the version command as directed by the command line args and 30 | returns an appropriate exit status.." 31 | [args] 32 | (run-cli-cmd #(do (show-version args) 0))) 33 | 34 | (defn -main [& args] 35 | (exit (cli args))) 36 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/command/constants.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.command.constants 2 | (:require [clojure.set :as set] 3 | [clojure.string :as str])) 4 | 5 | (def command-names 6 | {:configure-expiration "configure expiration" 7 | :replace-catalog "replace catalog" 8 | :replace-catalog-inputs "replace catalog inputs" 9 | :replace-facts "replace facts" 10 | :deactivate-node "deactivate node" 11 | :store-report "store report"}) 12 | 13 | (def command-keys (set/map-invert command-names)) 14 | 15 | (def supported-command-versions 16 | {"configure expiration" #{1} 17 | "replace facts" #{2 3 4 5} 18 | "replace catalog" #{4 5 6 7 8 9} 19 | "replace catalog inputs" #{1} 20 | "store report" #{3 4 5 6 7 8} 21 | "deactivate node" #{1 2 3}}) 22 | 23 | (def latest-catalog-version (apply max (supported-command-versions "replace catalog"))) 24 | (def latest-report-version (apply max (supported-command-versions "store report"))) 25 | (def latest-facts-version (apply max (supported-command-versions "replace facts"))) 26 | (def latest-configure-expiration-version (apply max (supported-command-versions "configure expiration"))) 27 | (def latest-catalog-inputs-version (apply max (supported-command-versions "replace catalog inputs"))) 28 | (def latest-deactivate-node-version (apply max (supported-command-versions "deactivate node"))) 29 | 30 | (def latest-command-versions 31 | {:replace_catalog latest-catalog-version 32 | :store_report latest-report-version 33 | :replace_facts latest-facts-version 34 | :configure_expiration latest-configure-expiration-version 35 | :replace_catalog_inputs latest-catalog-inputs-version}) 36 | 37 | (defn normalize-command-name 38 | "Normalize command name from an incoming request's query param" 39 | [command] 40 | (str/replace command "_" " ")) 41 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/constants.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.constants) 2 | 3 | (def filename-forbidden-characters 4 | [\/ \u0000 \\ \:]) 5 | 6 | (def sha1-hex-length 7 | "The length (in ASCII/UTF-8 bytes) of a SHA1 sum when encoded in hexadecimal." 8 | 40) 9 | 10 | ;; Use to signal when a change isn't backwards compatible with pdbext ha-sync. 11 | ;; Bumping this version number will cause pdbext sync requests to fail with 409s 12 | ;; until both pdbs are upgraded and on the same sync version. 13 | (def pdb-sync-ver 2) 14 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/core.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.core 2 | "PuppetDBs normal entry point. Dispatches to command line subcommands." 3 | (:require 4 | [clojure.string :as str] 5 | [puppetlabs.puppetdb.cli.util 6 | :refer [err-exit-status exit run-cli-cmd]])) 7 | 8 | (def usage-lines 9 | ["Available subcommands:" 10 | " version Display version information" 11 | " services Run PuppetDB" 12 | " upgrade Upgrade to latest version and exit" 13 | " benchmark Run development-only benchmarking tool" 14 | " fact-storage-benchmark" 15 | " generate Create sample data files for benchmarking" 16 | " help Display usage summary" 17 | "For help on a given subcommand, invoke it with -h"]) 18 | 19 | (defn usage 20 | [stream] 21 | (binding [*out* stream] 22 | (println (str/join "\n" usage-lines)))) 23 | 24 | (defn help [args] 25 | (if (zero? (count args)) 26 | (do (usage *out*) 0) 27 | (do (usage *err*) err-exit-status))) 28 | 29 | ;; Resolve the subcommands dynamically to avoid loading the world just 30 | ;; to print the version. 31 | (defn run-resolved [cli-name fn-name args] 32 | (let [namespace (symbol (str "puppetlabs.puppetdb.cli." cli-name))] 33 | (require (vector namespace)) 34 | (apply (ns-resolve namespace fn-name) args))) 35 | 36 | (defn run-subcommand 37 | "Runs the given subcommand, which should handle shutdown and the 38 | process exit status itself." 39 | [subcommand args] 40 | (case subcommand 41 | "help" (run-cli-cmd #(help args)) 42 | "upgrade" (run-resolved "services" 'cli [args {:upgrade-and-exit? true}]) 43 | "services" (run-resolved "services" 'cli [args]) 44 | 45 | ("benchmark" "fact-storage-benchmark" "version" "generate") 46 | (run-resolved subcommand 'cli [args]) 47 | 48 | (do 49 | (usage *err*) 50 | err-exit-status))) 51 | 52 | (defn -main 53 | [subcommand & args] 54 | (exit (run-subcommand subcommand args))) 55 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/factsets.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.factsets 2 | (:require 3 | [clojure.set :as set] 4 | [puppetlabs.puppetdb.schema :as pls] 5 | [schema.core :as s])) 6 | 7 | ;; SCHEMA 8 | 9 | (def fact-query-schema 10 | "Schema for a single fact map" 11 | {:name s/Str 12 | :value s/Any 13 | (s/optional-key :environment) s/Str 14 | (s/optional-key :certname) s/Str}) 15 | 16 | (def facts-expanded-query-schema 17 | "Facts expanded data format." 18 | {(s/optional-key :data) [fact-query-schema] 19 | :href String}) 20 | 21 | (def factset-query-schema 22 | "Final schema for a single factset." 23 | {(s/optional-key :certname) String 24 | (s/optional-key :environment) (s/maybe s/Str) 25 | (s/optional-key :timestamp) pls/Timestamp 26 | (s/optional-key :producer_timestamp) (s/maybe pls/Timestamp) 27 | (s/optional-key :hash) (s/maybe s/Str) 28 | (s/optional-key :facts) facts-expanded-query-schema}) 29 | 30 | (def facts-wireformat-schema 31 | {:certname s/Str 32 | :values {s/Keyword s/Any} 33 | :environment (s/maybe s/Str) 34 | :producer_timestamp (s/cond-pre pls/Timestamp (s/maybe s/Str))}) 35 | 36 | ;; TRANSFORMATIONS 37 | 38 | (pls/defn-validated fact-query->wire-v5 39 | [fact :- fact-query-schema] 40 | (-> fact 41 | (dissoc :environment :certname))) 42 | 43 | (pls/defn-validated facts-list-to-map :- {s/Keyword s/Any} 44 | [facts :- [fact-query-schema]] 45 | (zipmap (map (comp keyword :name) facts) 46 | (map :value facts))) 47 | 48 | (pls/defn-validated facts-expanded->wire-v5 :- {s/Keyword s/Any} 49 | [facts :- facts-expanded-query-schema] 50 | (facts-list-to-map 51 | (map fact-query->wire-v5 (:data facts)))) 52 | 53 | (defn factsets-query->wire-v5 [factsets] 54 | (map 55 | #(-> % 56 | (dissoc :hash :timestamp) 57 | (update :facts facts-expanded->wire-v5) 58 | (set/rename-keys {:facts :values})) 59 | factsets)) 60 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/honeysql.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.honeysql 2 | "Some generic HoneySQL extensions, candidates for re-usability and 3 | potential upstream submission.") 4 | 5 | ;; SCHEMA 6 | 7 | ;; COMMMON DIRECT SQL FUNCTIONS 8 | 9 | (defn coalesce 10 | "coalesce(arg, ...) sql function" 11 | [& args] 12 | (into [:coalesce] args)) 13 | 14 | (defn scast 15 | "cast(source AS target) sql function" 16 | [source 17 | target] 18 | [:cast source target]) 19 | 20 | (defn json-agg 21 | "json_agg(expr) sql function" 22 | [expr] 23 | [:json_agg expr]) 24 | 25 | (defn row-to-json 26 | "row_to_json(record) sql function" 27 | [record] 28 | [[:row_to_json record]]) 29 | 30 | ;; Misc honeysql functions 31 | 32 | (defn extract-sql 33 | "Returns a keyworidzed version of the SQL string if `k` is an sql raw, otherwise returns `s`" 34 | [s] 35 | (if (keyword? s) 36 | s 37 | (keyword (second s)))) 38 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/jdbc/internal.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.jdbc.internal 2 | "JDBC helper functions 3 | 4 | *External code should not call any of these functions directly, as they are* 5 | *subject to change without notice.*" 6 | (:require [puppetlabs.i18n.core :refer [tru]])) 7 | 8 | (defn limit-exception 9 | "Helper method; simply throws an exception with a message explaining 10 | that a query result limit was exceeded." 11 | [limit] 12 | (IllegalStateException. 13 | (tru "Query returns more than the maximum number of results (max: {0})" limit))) 14 | 15 | 16 | (defn limit-result-set! 17 | "Given a `limit` and a `result-set` (which is usually the result of a call to 18 | `clojure.java.jdbc/with-query-results`), this function verifies that the 19 | `result-set` does not contain more than `limit` results and then returns the 20 | results. 21 | 22 | If `limit` is zero, the original `result-set` is returned unmodified. 23 | 24 | Throws an exception if the `result-set` contains more than `limit` results." 25 | [limit result-set] 26 | {:pre [(and (integer? limit) (>= limit 0))]} 27 | (if (pos? limit) 28 | ;; we're doing a `take` with `limit + 1` here, so that we can 29 | ;; correctly identify whether the query *exceeded* the specified 30 | ;; limit. 31 | (let [limited-result-set (take (inc limit) result-set)] 32 | (when (> (count limited-result-set) limit) 33 | (throw (limit-exception limit))) 34 | limited-result-set) 35 | result-set)) 36 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/lint.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.lint) 2 | 3 | (defmacro ignore-value 4 | "Suppress eastwood's unused-ret-vals warning: 5 | https://github.com/jonase/eastwood#unused-ret-vals. See 6 | ./eastwood.clj for the suppression that makes this work." 7 | [x] 8 | ;; Use the dummy let to avoid https://github.com/jonase/eastwood/issues/355 9 | `(let [x# ~x] 10 | nil)) 11 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/meta/version.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.meta.version 2 | "Versioning Utility Library 3 | 4 | This namespace contains some utility functions relating to checking version 5 | numbers of various fun things." 6 | (:require [clojure.string :as string] 7 | [puppetlabs.puppetdb.jdbc :as jdbc] 8 | [puppetlabs.dujour.version-check :as version-check] 9 | [puppetlabs.puppetdb.scf.storage-utils :as sutils])) 10 | 11 | ;; ### PuppetDB current version 12 | 13 | (defn version 14 | "Get the version number of this PuppetDB installation." 15 | [] 16 | {:post [(string? %)]} 17 | (version-check/get-version-string "puppetdb" "puppetlabs")) 18 | 19 | ;; ### Utility functions for checking for the latest available version of PuppetDB 20 | 21 | (defn pdb-version-check-values* 22 | [db] 23 | (jdbc/with-db-connection db 24 | (let [{:keys [database version]} (sutils/db-metadata)] 25 | {:product-name {:group-id "puppetlabs" 26 | :artifact-id "puppetdb"} 27 | :database-name database 28 | :database-version (string/join "." version)}))) 29 | 30 | (def pdb-version-check-values 31 | (memoize pdb-version-check-values*)) 32 | 33 | (defn update-info 34 | "Make a request to the puppetlabs server to determine the latest available 35 | version of PuppetDB. Returns the JSON object received from the server, which 36 | is expected to be a map containing keys `:version`, `:newer`, and `:link`. 37 | 38 | Returns `nil` if the request does not succeed for some reason." 39 | [update-server db] 40 | (version-check/update-info (pdb-version-check-values db) update-server)) 41 | 42 | (defn check-for-updates! 43 | [update-server db] 44 | (try 45 | @(version-check/check-for-update (pdb-version-check-values db) update-server) 46 | (catch Exception _))) 47 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/metrics/core.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.metrics.core 2 | (:require [metrics.reporters.jmx :refer [reporter]] 3 | [metrics.core :refer [new-registry]])) 4 | 5 | (defn new-metrics [domain & {:keys [jmx?] :or {jmx? true}}] 6 | (let [registry (new-registry)] 7 | (if-not jmx? 8 | {:registry registry} 9 | {:registry registry 10 | :reporter (reporter registry {:domain domain})}))) 11 | 12 | (def metrics-registries {:admin (new-metrics "puppetlabs.puppetdb.admin") 13 | :benchmark (new-metrics "puppetlabs.puppetdb.benchmark") 14 | :mq (new-metrics "puppetlabs.puppetdb.mq") 15 | :dlo (new-metrics "puppetlabs.puppetdb.dlo") 16 | :http (new-metrics "puppetlabs.puppetdb.http") 17 | :population (new-metrics "puppetlabs.puppetdb.population") 18 | :storage (new-metrics "puppetlabs.puppetdb.storage") 19 | :database (new-metrics "puppetlabs.puppetdb.database")}) 20 | 21 | (defn keyword->metric-name 22 | "Creates a metric name from a keyword. Applies the prefix so that it 23 | can be grouped in a way that is easy to view as a set of JMX MBeans" 24 | [prefix metric-name] 25 | (->> metric-name 26 | (conj prefix) 27 | (mapv name))) 28 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/mq.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.mq 2 | (:require 3 | [clojure.java.jmx :as jmx] 4 | [metrics.timers :refer [timer]] 5 | [puppetlabs.puppetdb.metrics.core :as metrics])) 6 | 7 | (def mq-metrics-registry (get-in metrics/metrics-registries [:mq :registry])) 8 | 9 | (def metrics (atom {:message-persistence-time (timer mq-metrics-registry 10 | (metrics/keyword->metric-name 11 | [:global] :message-persistence-time))})) 12 | 13 | (defn queue-size 14 | "Returns the number of pending messages in the queue. 15 | Throws {:kind ::queue-not-found} when the queue doesn't exist." 16 | [] 17 | (try 18 | (jmx/read "puppetlabs.puppetdb.mq:name=global.depth" :Count) 19 | (catch javax.management.InstanceNotFoundException _ 20 | (throw (ex-info "" {:kind ::queue-not-found}))))) 21 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/nio.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.nio 2 | (:import 3 | [java.nio.file CopyOption Path OpenOption Paths StandardCopyOption])) 4 | 5 | (def copt-atomic StandardCopyOption/ATOMIC_MOVE) 6 | (def copt-replace StandardCopyOption/REPLACE_EXISTING) 7 | 8 | (defn copts ^"[Ljava.nio.file.CopyOption;" [opts] 9 | (into-array CopyOption opts)) 10 | 11 | (defn oopts ^"[Ljava.nio.file.OpenOption;" [opts] 12 | (into-array OpenOption opts)) 13 | 14 | (defn get-path ^Path [^String s & more-strings] 15 | (Paths/get s (into-array String more-strings))) 16 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/nodes.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.nodes 2 | "Puppet nodes parsing 3 | 4 | Functions that handle conversion of nodes from wire format to 5 | internal PuppetDB format, including validation." 6 | (:require 7 | [puppetlabs.puppetdb.schema :as pls] 8 | [schema.core :as s])) 9 | 10 | ;; SCHEMA 11 | 12 | (def expire-wireformat-schema 13 | {:facts s/Bool}) 14 | 15 | (def configure-expiration-wireformat-schema 16 | {:certname s/Str 17 | :expire expire-wireformat-schema 18 | (s/optional-key :producer_timestamp) (s/maybe pls/Timestamp)}) 19 | 20 | (def nodes-wireformat-schema 21 | {:certname s/Str 22 | :deactivated (s/maybe s/Str) 23 | :expired (s/maybe pls/Timestamp) 24 | :catalog_timestamp (s/maybe pls/Timestamp) 25 | :facts_timestamp (s/maybe pls/Timestamp) 26 | :report_timestamp (s/maybe pls/Timestamp) 27 | :catalog_environment (s/maybe s/Str) 28 | :facts_environment (s/maybe s/Str) 29 | :report_environment (s/maybe s/Str) 30 | :latest_report_status (s/maybe s/Str) 31 | :latest_report_hash (s/maybe s/Str) 32 | :latest_report_noop (s/maybe s/Bool) 33 | :latest_report_noop_pending (s/maybe s/Bool) 34 | :cached_catalog_status (s/maybe s/Str) 35 | :latest_report_corrective_change (s/maybe s/Bool) 36 | :latest_report_job_id (s/maybe s/Str) 37 | :expires_facts (s/maybe s/Bool) 38 | :expires_facts_updated (s/maybe pls/Timestamp)}) 39 | 40 | (pls/defn-validated nodes-query->configure-expiration-wire-v1 41 | :- [configure-expiration-wireformat-schema] 42 | [nodes :- [nodes-wireformat-schema]] 43 | (->> nodes 44 | (filter :expires_facts_updated) 45 | (map (fn [x] 46 | {:certname (:certname x) 47 | :expire {:facts (:expires_facts x)} 48 | :producer_timestamp (:expires_facts_updated x)})))) 49 | 50 | (def deactivate-node-wireformat-schema 51 | {:certname s/Str 52 | (s/optional-key :producer_timestamp) (s/maybe pls/Timestamp)}) 53 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/package_util.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.package-util 2 | (:require [schema.core :as s])) 3 | 4 | ;;; small utilities for manipulating package data; in a separate file to untangle 5 | ;;; a dependency loop. 6 | 7 | (def package-tuple 8 | [(s/one s/Str "package_name") 9 | (s/one s/Str "version") 10 | (s/one s/Str "provider")]) 11 | 12 | (def hashed-package-tuple 13 | (conj package-tuple 14 | (s/one s/Str "package_hash"))) 15 | 16 | (defn package-tuple-hash [hashed-package-tuple] 17 | (nth hashed-package-tuple 3)) 18 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/query/catalog_inputs.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.query.catalog-inputs 2 | (:require [puppetlabs.puppetdb.query :as query] 3 | [puppetlabs.puppetdb.schema :as pls] 4 | [puppetlabs.puppetdb.utils :as utils] 5 | [schema.core :as s])) 6 | 7 | (def row-schema 8 | (query/wrap-with-supported-fns 9 | {(s/optional-key :certname) s/Str 10 | (s/optional-key :producer_timestamp) pls/Timestamp 11 | (s/optional-key :catalog_uuid) s/Str 12 | (s/optional-key :inputs) [[s/Str]]})) 13 | 14 | (def converted-row-schema 15 | (query/wrap-with-supported-fns 16 | {(s/optional-key :certname) s/Str 17 | (s/optional-key :producer_timestamp) pls/Timestamp 18 | (s/optional-key :catalog_uuid) s/Str 19 | (s/optional-key :inputs) [[s/Str]]})) 20 | 21 | (pls/defn-validated convert-array-to-vec :- converted-row-schema 22 | [row] 23 | (utils/update-when row [:inputs] (partial map vec))) 24 | 25 | (defn munge-catalog-inputs 26 | [_ _] 27 | (fn [rows] 28 | (map convert-array-to-vec rows))) 29 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/query/common.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.query.common) 2 | 3 | ;; A macro so that if nothing else clojure.test ERROR message 4 | ;; file/line numbers will be right (only reports first stack entry). 5 | (defmacro bad-query-ex [msg] 6 | `(ex-info ~msg {:kind :puppetlabs.puppetdb.query/invalid 7 | :puppetlabs.puppetdb/known-error? true})) 8 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/query/edges.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.query.edges 2 | "Fact query generation" 3 | (:require [puppetlabs.puppetdb.schema :as pls] 4 | [puppetlabs.puppetdb.query :as query] 5 | [schema.core :as s])) 6 | 7 | ;; SCHEMA 8 | 9 | (def edge-schema 10 | (query/wrap-with-supported-fns 11 | {(s/optional-key :certname) String 12 | (s/optional-key :relationship) String 13 | (s/optional-key :source_title) String 14 | (s/optional-key :source_type) String 15 | (s/optional-key :target_title) String 16 | (s/optional-key :target_type) String})) 17 | 18 | ;; MUNGE 19 | 20 | (pls/defn-validated munge-result-rows 21 | "Reassemble rows from the database into the final expected format." 22 | [_ _] 23 | (fn [rows] 24 | (map #(s/validate edge-schema %) rows))) 25 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/query/fact_contents.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.query.fact-contents 2 | (:require [puppetlabs.puppetdb.facts :as f] 3 | [puppetlabs.puppetdb.scf.storage-utils :as sutils] 4 | [puppetlabs.puppetdb.query :as query] 5 | [puppetlabs.puppetdb.schema :as pls] 6 | [puppetlabs.puppetdb.utils :as utils] 7 | [schema.core :as s])) 8 | 9 | (def row-schema 10 | (query/wrap-with-supported-fns 11 | {(s/optional-key :certname) s/Str 12 | (s/optional-key :environment) (s/maybe s/Str) 13 | (s/optional-key :path) [s/Str] 14 | (s/optional-key :path_types) s/Str 15 | (s/optional-key :name) s/Str 16 | (s/optional-key :value) (s/maybe s/Any)})) 17 | 18 | (def converted-row-schema 19 | (query/wrap-with-supported-fns 20 | {(s/optional-key :certname) s/Str 21 | (s/optional-key :environment) (s/maybe s/Str) 22 | (s/optional-key :path) f/fact-path 23 | (s/optional-key :name) s/Str 24 | (s/optional-key :value) s/Any})) 25 | 26 | (defn adjust-path-types 27 | "Adjusts the types in the :path based on the signature provided by 28 | path_types to ensure that array indexes are returned as integers 29 | rather than strings." 30 | [{:keys [path path_types] :as row}] 31 | (if-not path 32 | (do 33 | (assert (not path_types)) 34 | row) 35 | (do 36 | (assert path_types) 37 | (assert (= (count path) (count path_types))) 38 | (-> row 39 | (dissoc :path_types) 40 | (assoc :path (mapv (fn [^String part sig] 41 | (case sig 42 | \s part 43 | \i (Long/valueOf part))) 44 | path path_types)))))) 45 | 46 | (pls/defn-validated munge-result-row :- converted-row-schema 47 | "Coerce the value of a row to the proper type, and convert the path back to 48 | an array structure." 49 | [row :- row-schema] 50 | (-> (adjust-path-types row) 51 | (utils/update-when [:value] sutils/parse-db-json))) 52 | 53 | (pls/defn-validated munge-result-rows 54 | "Munge resulting rows for fact-contents endpoint." 55 | [_ _] 56 | (fn [rows] 57 | (map munge-result-row rows))) 58 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/query/facts.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.query.facts 2 | "Fact query generation" 3 | (:require [puppetlabs.puppetdb.cheshire :as json] 4 | [puppetlabs.puppetdb.scf.storage-utils :as sutils] 5 | [puppetlabs.puppetdb.facts :as facts] 6 | [puppetlabs.puppetdb.query :as query] 7 | [puppetlabs.puppetdb.utils :as utils] 8 | [puppetlabs.puppetdb.schema :as pls] 9 | [schema.core :as s])) 10 | 11 | ;; SCHEMA 12 | 13 | (def row-schema 14 | (query/wrap-with-supported-fns 15 | {(s/optional-key :certname) s/Str 16 | (s/optional-key :environment) (s/maybe s/Str) 17 | (s/optional-key :name) s/Str 18 | (s/optional-key :value) s/Str})) 19 | 20 | (def converted-row-schema 21 | (query/wrap-with-supported-fns 22 | {(s/optional-key :certname) s/Str 23 | (s/optional-key :environment) (s/maybe s/Str) 24 | (s/optional-key :name) s/Str 25 | (s/optional-key :value) s/Any})) 26 | 27 | ;; MUNGE 28 | 29 | (pls/defn-validated deserialize-fact-value :- converted-row-schema 30 | "Coerce values for each row to the proper stored type." 31 | [row :- row-schema] 32 | (utils/update-when row [:value] json/parse-string)) 33 | 34 | (defn munge-result-rows 35 | [_ _] 36 | (fn [rows] 37 | (if (empty? rows) 38 | [] 39 | (map #(utils/update-when % [:value] sutils/parse-db-json) rows)))) 40 | 41 | (defn munge-path-result-rows 42 | [_ _] 43 | (fn [rows] 44 | (map #(utils/update-when % [:path] facts/string-to-factpath) rows))) 45 | 46 | (defn munge-name-result-rows 47 | [_ _] 48 | (fn [rows] 49 | (map :name rows))) 50 | 51 | (defn munge-package-inventory 52 | [_ _] 53 | (fn [rows] 54 | (map #(utils/update-when % [:package_inventory] (partial map vec)) rows))) 55 | -------------------------------------------------------------------------------- /src/puppetlabs/puppetdb/query/resources.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.query.resources 2 | "Resource querying 3 | 4 | This implements resource querying, using the query compiler in 5 | `puppetlabs.puppetdb.query`, basically by munging the results into the 6 | right format and picking out the desired columns." 7 | (:import [org.postgresql.util PGobject]) 8 | (:require [puppetlabs.puppetdb.query :as query] 9 | [puppetlabs.puppetdb.schema :as pls] 10 | [puppetlabs.puppetdb.utils :as utils] 11 | [schema.spec.core :as spec] 12 | [schema.spec.leaf :as leaf] 13 | [schema.core :as s])) 14 | 15 | ;; SCHEMA 16 | 17 | (defrecord OptionalNameMatching [pattern] 18 | s/Schema 19 | (spec [this] (leaf/leaf-spec 20 | (spec/precondition this 21 | #(re-matches pattern (name %)) 22 | #(list 're-matches pattern %)))) 23 | (explain [_] '(re-matches pattern))) 24 | 25 | (defn optional-matching-keyword 26 | "A regex pattern to check the keyword for." 27 | [pattern] 28 | (->OptionalNameMatching pattern)) 29 | 30 | (def row-schema 31 | "Resource query row schema." 32 | (query/wrap-with-supported-fns 33 | {(s/optional-key :certname) s/Str 34 | (s/optional-key :environment) (s/maybe s/Str) 35 | (s/optional-key :exported) s/Bool 36 | (s/optional-key :file) (s/maybe s/Str) 37 | (s/optional-key :line) (s/maybe s/Int) 38 | (s/optional-key :parameters) (s/maybe PGobject) 39 | (optional-matching-keyword #"parameters\..*") (s/maybe PGobject) 40 | (s/optional-key :resource) s/Str 41 | (s/optional-key :tags) [(s/maybe s/Str)] 42 | (s/optional-key :title) s/Str 43 | (s/optional-key :type) s/Str})) 44 | 45 | ;; MUNGE 46 | 47 | (pls/defn-validated row->resource 48 | "Convert resource query row into a final resource format." 49 | [row :- row-schema] 50 | (utils/update-when row [:parameters] #(or % {}))) 51 | 52 | (pls/defn-validated munge-result-rows 53 | "Munge the result rows so that they will be compatible with the version 54 | specified API specification" 55 | [_ _] 56 | (fn [rows] 57 | (map row->resource rows))) 58 | -------------------------------------------------------------------------------- /test-resources/binary-template.erb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/puppetdb/2c2efc97da49502083c0aa8269f9d1ddd9cb9541/test-resources/binary-template.erb -------------------------------------------------------------------------------- /test-resources/ca.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw 3 | ZXQgQ0E6IGxvY2FsaG9zdDAeFw0yMDAyMTIxNzAwNTNaFw0yNTAyMTExNzAwNTNa 4 | MB8xHTAbBgNVBAMMFFB1cHBldCBDQTogbG9jYWxob3N0MIICIjANBgkqhkiG9w0B 5 | AQEFAAOCAg8AMIICCgKCAgEAqwoaYxVI8tg0nZUCeZrWNe6y7WcN5Cd4ZPX5OnLm 6 | Co+8ccWM1E7fAbktUKZRXaEdvlSY6iQVX/4AJsNwg3FObSTd/J/OhM0vC5CNn8Si 7 | bu97mPcKtlZkgcDU0shLKdElpvFLO+vtWW8TJ8zOoDZh++NCasEM8jsPn4OXF6xA 8 | wbqLx4rvHqMTJfvn/roX5jH6+OlV7BYHpZTEfhVI6SqpGzUqpv6fkEgWiqomXmyH 9 | 77D8Xau7bRUbUmm993O/jhZIY3VeOrKkXsLV3OW2N6qJn9EUFgJiLp8aZw+Ek5oI 10 | /ElKRYK8d8OcRGz21HwfBkRybGMVZ9FzVpink1WN7d1Mn7IoTKWafVu1AHO61JeT 11 | JwcFtTiIaFBpdGP47I8vm+F+K5wPcQAdLRSdeowKQWbYrFzqhRsOghsfwYzW0s/L 12 | ussxS05Y2OjUUlEW483Y034HmC6r8NhxAwPLJhUMlA0JXzbAYrZb64Kz9NOFAt5e 13 | XbYAiVKUC91At7mHlwKV5znwGuGzqW+6qzO40kZKLkAiDhDVmfKnJFfOZBRfG/4A 14 | MBMjJMNrcDr6fNcTk4CtJHJ04bnbyZf80D9Ah0kf6JfEpJa64FQeoiq/bbdkR/Vv 15 | xCwuKIbynwJDb07oPR8mIJYfKbHpEmgcO18IVbhwXB+pPAp5BwMjqtnStvLTGqSU 16 | qM0CAwEAAaOBqTCBpjAxBglghkgBhvhCAQ0EJBYiUHVwcGV0IFNlcnZlciBJbnRl 17 | cm5hbCBDZXJ0aWZpY2F0ZTAxBgNVHSMEKjAooSOkITAfMR0wGwYDVQQDDBRQdXBw 18 | ZXQgQ0E6IGxvY2FsaG9zdIIBATAdBgNVHQ4EFgQUCWh5PzRBWoK2n8foCm3yK1mD 19 | bnkwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEL 20 | BQADggIBAIsouxaIkXGpUdhfy0dXPW7oKNMql/DfO3Q5Ey/nFL/d/SDKy5n6EcDN 21 | Noq6Hpyg9q/sSEXciL4HBvB/p5gwnW2B5SAsp5ldkUtkH9liF3OhdJWsnrzc6bTm 22 | sOaHCuX1KOwnLK+vAVUfNr8pxhAMZcpSPFHi+dtbh2Yj0RMuiKfWbMbgsmHjkI4P 23 | kXGoI4Sjkhq1DXJvw6DRUzdmjq/huwF01M/c74y9CZ4AG7AKVr1uw2NKowFESJZK 24 | VK9IExfxtsJvcLKZ5y1UVundiEfU0znyozq24yLnmdmQ8y36jDNNAUP0Rd1i0M0M 25 | Y/1cB/XpBnrKa8/YNoKPVOfxzSSkuBOTglUTS/lzC85z+N4f4PbMroQmymEbWjBy 26 | +z3aTtwzfh0lZnpNfZCHMpdxFQu0O/6srt/vdRnAWvpyEMdGF6waQD0P4Ao26m8f 27 | xssOuF5qFAVivO2dN8NfhpOArFb4fyuw8wzRb2pYzPvxuAflR8n7jHyT6E81wQSi 28 | djqEiWPT6c9S7up8AjHQiBycz3A5k7QIypOxzxd2N5N45RctBj4lG5Czlje0LEhY 29 | 0sDB45Z9UAn7HB5gR8ZcuLqq5j6StwU8rjrnVVwzOi/xAYl4VKy0mnQILODDIPnL 30 | Vofy0nNkhHcs/bXH9zu+RoR7DV2iKSYuWdc13OJtTCUEkQqT/AYQ 31 | -----END CERTIFICATE----- 32 | -------------------------------------------------------------------------------- /test-resources/create-test-db.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | createuser -DRSP puppetdb 3 | createuser -dRP --superuser pdb_test_admin 4 | createuser -DRSP pdb_test 5 | createdb -E UTF8 -O puppetdb puppetdb_test 6 | -------------------------------------------------------------------------------- /test-resources/integration-bootstrap.cfg: -------------------------------------------------------------------------------- 1 | puppetlabs.trapperkeeper.services.webserver.jetty10-service/jetty10-service 2 | puppetlabs.trapperkeeper.services.webrouting.webrouting-service/webrouting-service 3 | puppetlabs.trapperkeeper.services.metrics.metrics-service/metrics-webservice 4 | puppetlabs.trapperkeeper.services.status.status-service/status-service 5 | puppetlabs.trapperkeeper.services.scheduler.scheduler-service/scheduler-service 6 | puppetlabs.puppetdb.cli.services/puppetdb-service 7 | puppetlabs.puppetdb.command/command-service 8 | puppetlabs.puppetdb.pdb-routing/maint-mode-service 9 | puppetlabs.puppetdb.pdb-routing/pdb-routing-service 10 | puppetlabs.puppetdb.config/config-service 11 | puppetlabs.puppetdb.dashboard/dashboard-redirect-service 12 | -------------------------------------------------------------------------------- /test-resources/integration-puppetdb.conf: -------------------------------------------------------------------------------- 1 | global: { 2 | vardir: "" # filled out by the test harness 3 | logging-config: test-resources/logback-test.xml 4 | } 5 | 6 | database: { 7 | # These will be replaced by the test harness 8 | subname: "//localhost:5432/puppetdb" 9 | username: puppetdb 10 | password: puppetdb 11 | } 12 | 13 | command-processing: { 14 | threads: 6 15 | } 16 | 17 | nrepl: { 18 | enabled: false 19 | } 20 | 21 | jetty: { 22 | host: 0.0.0.0 23 | port: 0 24 | 25 | ssl-host: 0.0.0.0 26 | ssl-port: 0 # filled out by the test harness 27 | 28 | # Original settings 29 | 30 | ssl-ca-cert: ./test-resources/puppetserver/ssl/certs/ca.pem 31 | ssl-cert: ./test-resources/puppetserver/ssl/certs/localhost.pem 32 | ssl-key: ./test-resources/puppetserver/ssl/private_keys/localhost.pem 33 | 34 | ssl-protocols: ["TLSv1", "TLSv1.1", "TLSv1.2"] 35 | 36 | acceptor-threads: 4 37 | selector-threads: 4 38 | max-threads: 32 39 | } 40 | 41 | puppetdb: { 42 | } 43 | 44 | web-router-service: { 45 | "puppetlabs.trapperkeeper.services.metrics.metrics-service/metrics-webservice": "/metrics" 46 | "puppetlabs.trapperkeeper.services.status.status-service/status-service": "/status" 47 | "puppetlabs.puppetdb.pdb-routing/pdb-routing-service": "/pdb" 48 | "puppetlabs.puppetdb.dashboard/dashboard-redirect-service": "/" 49 | } 50 | -------------------------------------------------------------------------------- /test-resources/localhost.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFmjCCA4KgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw 3 | ZXQgQ0E6IGxvY2FsaG9zdDAeFw0yMDAyMTIxNzAwNTVaFw0yNTAyMTExNzAwNTVa 4 | MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC 5 | AgoCggIBAJGtAqTOjTETj3Lwglz0oEIM/HCz8OMhodOw/U/Nlc6rVqr40xS+VLZP 6 | roJKjDCx0WqidNwXE52Pwm/WHa5hts2wN1SmsgitL9u0KOh1LnF74ipNbxIBcraI 7 | Pwt4fOFJ/7SpbTm7hBxj2M3xfV34kLJfDBT42kZc6y8ysrT/E5BRQCICssZ3gny5 8 | bsB2nWf9Lh3boTMCn9KeaUCWGmMaj7S0NtDrwW2XOeinoNgxQWNdmPkPc1URaCT/ 9 | 0+IlbTbGukAcb5SPhUEIZlYZpEzPzvjq3av07OKP1xPoHleEx6XEweba795s8vOa 10 | 9sp4+rqoxHHRbyhHhAvQrNWcA/p7ktB1HMinfLNdu8I9o67N6+lA++T7zL7VYYQG 11 | ZNZ2BDSC85xUCCO2Qrro3G8tQD0Fj5XA08x5lHNKAAIM99zlpDEbudgILtpzEfth 12 | zjIW/tSxWZswHBXVP6tTnrlkTLK6gqR7ymlnuyQBG83di3CZy4wu282ZKTj3Dv76 13 | 5/yGryT22kxLSjacy+inl99RDxtSLkPJgGk9Snbb2nkPspdqJQWNMvizIrKPH0eK 14 | 3xP7KzV3QkbUX96Ihjd8xWVOdJpyJC+BFlcal47CLdTOu7xURzUk8kQ2FArXrNcS 15 | GOypf8t0EqtHLZvmldT+8xub5GM23JlLm+nKD93jaSPzPKhwVaZVAgMBAAGjgesw 16 | gegwMQYJYIZIAYb4QgENBCQWIlB1cHBldCBTZXJ2ZXIgSW50ZXJuYWwgQ2VydGlm 17 | aWNhdGUwHwYDVR0jBBgwFoAUCWh5PzRBWoK2n8foCm3yK1mDbnkwHQYDVR0OBBYE 18 | FBBmEcU80LZ6UTVG9Zxp54ATQcg+MBUGCysGAQQBgoxMAQMnBAYMBHRydWUwHAYD 19 | VR0RBBUwE4IGcHVwcGV0gglsb2NhbGhvc3QwDAYDVR0TAQH/BAIwADAgBgNVHSUB 20 | Af8EFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYDVR0PAQH/BAQDAgWgMA0GCSqG 21 | SIb3DQEBCwUAA4ICAQAtyI44zvwv2Vu7FAWFovXR7kz5ODr/ZlF+UsSpAOX02sqW 22 | yP4/h84osQ+OqyyCPA5wABJOH4IehkV1msgsk+GRfRlwo0IlJdfcErUcD92JdvLh 23 | f0lRssYDXRz+X2AioEIZT/YKM37kaFiyaM00YrW7OvUdbD5Ctq1nUprF70cjXZC1 24 | DfDwKGGQYcvy+U/jx8IybgkvGluOXqZbb/NVgU3/AhFdhiXnD/uMitBmov6w0yzH 25 | BgtYGZ8tlUvo2NFauAIwX1BTaurL8D9aM6HwmZsNt2VR3xPRIeQcf+dbU/xZLMEI 26 | 6BF9fRXKzF7NhnunZu8waSUKd/jI60zUNE8UlfXMCKn9h7ePBhmf5DwZBqF3Y5f3 27 | Vdjg8xYnkgbg8X8gaginOPJUZyB1/xOFTlsrxFYPCvl24UFq3W+Ndwif03kWfoqD 28 | GkqfzsIighAd6oO++voKpraxgS5Hk9G83C7swlYwyHEYBlEOmqv+U5zw60tupaU8 29 | OQXnG2eW+jKUpfhSx4OxHBPwF75ND1D9j4QXAnafcP0Bnm7y6YObiReKfnqYwQky 30 | Ks4JVxXZnJJq090/2gYLQrGAfacecjspR+BYIZdtDNMMvk1ghIqq/6OAjKYPE9wG 31 | y9atAFS9KgQGjCwfVKzlGn6LWT0gRq1AJGdcnL9TeDv/zF6GFNj8jzFSC7CNqw== 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /test-resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d %-5p [%thread] [%c{2}] %m%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/puppetdb/cli/export/tiny-catalog.json: -------------------------------------------------------------------------------- 1 | { 2 | "certname" : "myhost.localdomain", 3 | "code_id" : null, 4 | "producer_timestamp": "2014-07-10T22:33:54.781Z", 5 | "edges" : [ { 6 | "relationship" : "contains", 7 | "target" : { 8 | "title" : "/etc/apt/preferences.d/puppetlabs.pref", 9 | "type" : "File" 10 | }, 11 | "source" : { 12 | "title" : "puppetlabs", 13 | "type" : "Apt::Pin" 14 | } 15 | } ], 16 | "resources" : [ { 17 | "exported" : false, 18 | "title" : "/etc/apt/preferences.d/puppetlabs.pref", 19 | "line" : 60, 20 | "parameters" : { 21 | "group" : "root", 22 | "mode" : "0644", 23 | "content" : "Package: *\nPin: origin \"apt.puppetlabs.com\"\nPin-Priority: 900\n", 24 | "ensure" : "present", 25 | "owner" : "root" 26 | }, 27 | "tags" : [ "file", "apt::pin", "apt", "pin", "puppetlabs", "class", "os::linux::debian", "os", "linux", "debian", "os::linux", "role::base", "role", "base", "role::server", "server", "node", "myhost.localdomain" ], 28 | "type" : "File", 29 | "file" : "/Users/nicklewis/projects/puppetlabs-modules/dist/apt/manifests/pin.pp" 30 | }, { 31 | "exported" : false, 32 | "title" : "puppetlabs", 33 | "line" : 74, 34 | "parameters" : { 35 | "priority" : "900", 36 | "origin" : "apt.puppetlabs.com", 37 | "wildcard" : true, 38 | "ensure" : "present", 39 | "release" : "" 40 | }, 41 | "tags" : [ "apt::pin", "apt", "pin", "puppetlabs", "class", "os::linux::debian", "os", "linux", "debian", "os::linux", "role::base", "role", "base", "role::server", "server", "node", "myhost.localdomain" ], 42 | "type" : "Apt::Pin", 43 | "file" : "/Users/nicklewis/projects/puppetlabs-modules/site/os/manifests/linux/debian.pp" 44 | } ], 45 | "version" : "1330463446", 46 | "transaction_uuid" : "68b08e2a-eeb1-4322-b241-bfdf151d294c", 47 | "catalog_uuid" : "68b08e2a-eeb1-4322-b241-bfdf151d294c", 48 | "environment" : "DEV" 49 | } 50 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/puppetdb/ssl/certs/ca.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFNDCCAxygAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw 3 | ZXQgQ0E6IGV4cGxvc2l2bzAeFw0xMzAxMDEyMTQ0MTZaFw0xODAxMDEyMTQ0MTZa 4 | MB8xHTAbBgNVBAMMFFB1cHBldCBDQTogZXhwbG9zaXZvMIICIjANBgkqhkiG9w0B 5 | AQEFAAOCAg8AMIICCgKCAgEAv55rxHbHHFuov+Js47hU8n394nGYplAocF88hDgX 6 | 6MLG75pzXZ7WqA+uEHxm7KkarEXxBZqkTUlWsxFa0UpgjEQlRDUxnlLsbJL1/HYP 7 | SB1+J7a8UNGvZRh2Ich3rbQ8+tv4UQRR8dr7tOQE+EPL0M492FYx/t/0pRHDErKD 8 | RJOHxxJLkpapIavObg/bZDEoLf8+ZaU/DyBENJmL4lhHl6i/KhBinuR4UnUfdxZ7 9 | dVTid7gNGk9VGot3x0LWdXYqQ/sxNb/qx6M/0MR5PuO9Pdsmn1SHyRyUcIjX1l6Y 10 | H4YH+ryoff0EWEtJxsGrrptXWX7groQpyRZrdknU74cCKyR1JY+7DyV7D8Ixgf1j 11 | MU7GKEglVB0qHURWzQgfsNeq3kk9I+dQr8KQvkv83cVYVM7mONA+EyMju8i7u4Oq 12 | 5XvpZvBANw+UZwB2lNTDdtBdC+XHQIAM9DYwpLyz20WlAmAZOFzHqe3k6ewwbU+n 13 | UEZgauvnmFsN1DbYeLtLabm1P7QgI4pxGfXXhOVCexIDTZ8mv1s3fsCP0tXmKQhp 14 | j25FvNJ6k/1xBPKc/PHB2Bms402GaK7lknaYBxIGUzgT2sw/GlcxWiPnV6BUHPwW 15 | aivELyu/hRu+Jr6bMsmlC0ZS4ZllrvsAitTPYvHdshQ6BmyHkSr6ZzrcijILGfFg 16 | 0esCAwEAAaN7MHkwNwYJYIZIAYb4QgENBCoWKFB1cHBldCBSdWJ5L09wZW5TU0wg 17 | SW50ZXJuYWwgQ2VydGlmaWNhdGUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF 18 | MAMBAf8wHQYDVR0OBBYEFPdrBes9dJY2zNm2UsqhdDwtGMncMA0GCSqGSIb3DQEB 19 | CwUAA4ICAQC0oieRsLuDOMYdsUVWj2qsSjjf7SgpdjdBJ23eY9DO1ePz4/MkJG8d 20 | 5oWFy9bTBWEDev7/9MWizHtjk/V+AglLaPJB2GyR9zfGeodRx860iqQdhrEs3B9U 21 | pGat1kKCDY3yee38Up4I0HyPdjTCPu0FcM+k4ySu1HKvhr0elOo3Y4d/UWGFfc6U 22 | bF4K385j1IKtN2O7Iu6DoYZNu+InZ95xiRhApzTRJop3PM+FznYNavFaOlFS5mcj 23 | tbKiQjN+8XrpmHJVQniEz4qKY5yZO+IbPBxP8lZOJYvKYtMu2KsbxDd8s/6s40dT 24 | SpHu7lEgBe4gQXDMkegHo4npJoiXlHh97pgRgj6DLeUiKtrq31NYRD5gQ+KpKdtg 25 | z4mvOcJUXitMV3LtoUGnYNwUXNjvNuMAiFlAQ5fRDTX5dnJTxa3+qMn07zV2J+9a 26 | +Wdqy6x4IBFHdpfhiySeJ0ERq7JnOiRZHsTqGSF6Bg+X1S7b+cXnXyvhnEZbAomF 27 | kU8pJt6XBLvtlq5s5wqKdndqLdQGdcvHcEcEi+s4zDwQsVmYeFkSnk+uiRESp4s3 28 | 8y3ecGihNxpfl2Ro2mrrf/2qj+voZ+brs0XzQiT6yuZX1B7I7IF28Q3qwweDAjut 29 | s1G1ntQA9La615iefs2DAkdCS4ROU8/TFz30I08PNpOrwMhg6QDGGA== 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/puppetdb/ssl/certs/localhost.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFSjCCAzKgAwIBAgIBAzANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw 3 | ZXQgQ0E6IGV4cGxvc2l2bzAeFw0xMzAxMDEyMTQ0MjhaFw0xODAxMDEyMTQ0Mjha 4 | MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC 5 | AgoCggIBANCEYBvEIdTXFOMwz18wahs6tg26C+LT2XOwQspb/Aj5WT2EBwnG2leD 6 | CzfOAKyhHDL6jRqrYU32jqoqBzmzkeVsHzqOMNFosyvcBLU8zyLZU+IP1rjJCyE8 7 | xx9HsdhPKJj93f/gSNR5NQlRcZfqahhOwh/nYdY3pFiNgjUoRwhV2Q01n+ku8WJw 8 | kLVT1TREW9TiSWk7cHWF/ZltPOMMxvJ9q0kXh8sVYK4Gtt3pphTUW0qgXQ2NnNWT 9 | W+7vciRjnHxeoY3q6ZG7vZ8HewYKR4W8D6FA32xCsWELSsWlAABt1lBjKGas/fiY 10 | SeDqSfIxknFn/CIM9AIp2PLS3wh5e0o98qey9AN2WRyG7Qs0ijhwKx9bsMxbM0LR 11 | 5jXuXjBnjGQ69fwCjwlUsOSpNPWLibM+GmxvhghJgAlH5dD4+GqN77WLncQTWYXX 12 | GnOw5efVivS4bgU3t8l8mHLH6quLolR1KLfCv+HuqkvRposAqqLwKH+dhlbq1Y+i 13 | 4siPxfYV5NZ092Z9R0F4BPEmLhKngkK+/eQXxLY2zfaR6Ns83yRJfMXRyElECX/+ 14 | RBT1LyIRZg+MbsRg7DsKWI0plzxso/4CgSmYSfPku5nkekrMN34YhUtcxsdHSmY1 15 | 5/p2olvKpTJj3e5fa2KVswcv77FsC17gIfMXqvN3tITP+q1LLJHNAgMBAAGjgZsw 16 | gZgwNwYJYIZIAYb4QgENBCoWKFB1cHBldCBSdWJ5L09wZW5TU0wgSW50ZXJuYWwg 17 | Q2VydGlmaWNhdGUwDgYDVR0PAQH/BAQDAgWgMCAGA1UdJQEB/wQWMBQGCCsGAQUF 18 | BwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBT3awXrPXSWNszZ 19 | tlLKoXQ8LRjJ3DANBgkqhkiG9w0BAQsFAAOCAgEAYTFx++uptZxgptFmkPfT1f2W 20 | 6djOOVULmlLGPC6Ovbe5v0ksA2hbLW3eSmfL28Ku0WC8gRl0/PhyiyW77M1jp9dV 21 | ztsFkXjMiIIcY0B7Hgqh1kpK1CFvSbsD3piXcDLlZ1CwSAXuohp+J2fUblHRfAUD 22 | Th9qrm3g4uNFp0wXxO1+GgXeDrGRqYosb0wAhB7/BhW2WbOFtVYdFoyyXJFJYx/3 23 | Gj7ZTE3rvGGxOEEuww0pFmuGCflZYxEu15Rynej7soGaE80+wRk+gMS26WKwRQ/0 24 | TGovOHSLo/fpOjjHIoqbQLH3S08jUfAYjjP7Rd01SiztUjZMILC2WCnpdYN+2O9O 25 | rGTj2Zl3oRtE67NwxgKlo2GIFghSF366XOF8O4z1e9id6u5XEdoz8uGFkHyMu79N 26 | cdYcUtmAqLvJ0Ubewg+TfNDcfk1akNtHtIJDNqFwHlZ9R1GIupHQs10R4YxJv3I2 27 | LojJbtcgWcDg9StwCHRA0SuLrWnHPnm+glzXM5HTNJZ6vcrM0SrcnZ59p3o3ZULL 28 | JTJikA+pcs+WAWz1yTNg/ywxYPnFrs8A4MEC43XFe2dS96a7VcNqpMMya+DAWWCS 29 | +51lDlMLuz+q5WHDGh3ouTNYMdcSLo8bHzKInDYnK/DzUpdJ5OKYwqfxv5n0bJs6 30 | fRA2buaQo0zJeid7G2Q= 31 | -----END CERTIFICATE----- 32 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/puppetdb/ssl/private_keys/keyonly.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC3986OFH0Vkw3i 3 | bJ8BicJzJjqEuYwZYrm9QPBN1fTOgEXHQrGVL8L1XA6QT1XknBT4o3zw+PuQuvUy 4 | Gm9pyTl4/wkt5llBPg6tfL7JhgFpKvDaZzxa51lKvnRUVYuLwNL+hKPvvsPOLdcF 5 | +/x3+cGzc+M7FpPLm/V+VGqiCoc9LnDOh9iSUD5ONrKjzHVzNT0IFSSGNEhYMIcG 6 | Ogf0hmFCnd1w9mcghnm+qMKN5LVdT6maPtpTAKaDYVvX0UiZldWP172r2fu22sNN 7 | B5JNMJ4LFQ7pOO6psyMZmPidhCBHlueya2Vq3PURH9G3heYhQyX/AYnXaT7wTZk4 8 | Jfr+oVCnAgMBAAECggEAWQHQMfW/vxxy70XWeIwKRGQOlAChw/Z8HxC4MzB9TRvK 9 | pumhuahuDwAHG9MGn6DUlKek34HXVOLfluorVWdCI0RhUI/ORz6bI1zjgeUP8a4Q 10 | 8dpY3TJphTw4VEU/StJ0QygxmOEXIz4SdpbAQ9vW19gN7JyzzSMb149IODYX0IVA 11 | 8bJI1oV9ig2vp+JZyOVQLpXn5EdKlHtVjInSGOMPyFNZ1QkcyQFoozSw/XJ8vyk3 12 | 4bskjaTyF85cgkTgwy674iVnKu+3wVpcyzq8elJDEzKz6CH6nQO6/xTHv+tm6yQu 13 | f3HuXEaIysGw0i6qbEtP5VSx6DCANcwdWUwtTVrboQKBgQDqxh23m/2uh2U9d5xW 14 | BhUWIGXBIBgEYxdXayh69796Bg2HHtOt5VeRPXHHLGaieYC9qUUHm2ppJBx2LdDQ 15 | M7UGoShmyUrnA8HDrjn6BHkmeFGjDdsw5Y4t2QRh3B0rEFIwYoSonYpnWDnJh6Qe 16 | SU/adCN+j8z59HcIqLC20bLU7QKBgQDImcd45OWZTqfptiJ7HfJApQtX8uv+fk2V 17 | dtbJEOMfmIOH9GSGguygUjccC7jVGMm63KNaDs1/gW7o8/pPUZGhGV48oG2qmlfD 18 | FlRc6vmxNSBv73h1h/XfTS1aKjzSm5U+66e3S0v9ObO4Y0ybSQhI/GkkuIaIK6G0 19 | hnfDqZ69YwKBgHkK7fVlUpSyL+tSCON9PU/sIipBHsDcSgODNxq3Mxx5lG3u4dpN 20 | XSl/0XKMHNp15H9kjzeN1H4i5R21H2zIy/OAEXF1JM4YbMUzxaZ2ufOwov57PWBn 21 | ajePJShDMTKrtoRFtvmsR9hib2DNMzt+NtJ9gHNXNqpEdT6cooePdDE9AoGABG0Q 22 | L6StRDKuFcQFAr5oZ/C8TVZ4yoay44dZudn7iOjujgNgbG9bFTZ7LM09aMZBPTQ9 23 | DnGhKx0J+23WqgVctzc+EwxfHxKEuTM27U3p8HUBoDaia8VyMVkclQ61hNgV9Oty 24 | KeMpbA7n3juipxJ3clTPZRYFMd/0k20cG18Ut40CgYEAngAQc4wZjvQSLlcmHw2V 25 | xWa5Reug51D609MRXfHJOXtyVmlAFAOcTe/P/xr+0R7uAz9JHiSLBiXzxROmeczW 26 | HjO5uOTfh+UjUl8Dfy5R4mq3XVLtdMTfBG8lxPsKUMUvOEwc+JHh0JriwN2+aVqv 27 | CRMCwm+RRhWwCqOoqKfNBio= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /test-resources/puppetlabs/puppetdb/ssl/public_keys/localhost.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0IRgG8Qh1NcU4zDPXzBq 3 | Gzq2DboL4tPZc7BCylv8CPlZPYQHCcbaV4MLN84ArKEcMvqNGqthTfaOqioHObOR 4 | 5WwfOo4w0WizK9wEtTzPItlT4g/WuMkLITzHH0ex2E8omP3d/+BI1Hk1CVFxl+pq 5 | GE7CH+dh1jekWI2CNShHCFXZDTWf6S7xYnCQtVPVNERb1OJJaTtwdYX9mW084wzG 6 | 8n2rSReHyxVgrga23emmFNRbSqBdDY2c1ZNb7u9yJGOcfF6hjerpkbu9nwd7BgpH 7 | hbwPoUDfbEKxYQtKxaUAAG3WUGMoZqz9+JhJ4OpJ8jGScWf8Igz0AinY8tLfCHl7 8 | Sj3yp7L0A3ZZHIbtCzSKOHArH1uwzFszQtHmNe5eMGeMZDr1/AKPCVSw5Kk09YuJ 9 | sz4abG+GCEmACUfl0Pj4ao3vtYudxBNZhdcac7Dl59WK9LhuBTe3yXyYcsfqq4ui 10 | VHUot8K/4e6qS9GmiwCqovAof52GVurVj6LiyI/F9hXk1nT3Zn1HQXgE8SYuEqeC 11 | Qr795BfEtjbN9pHo2zzfJEl8xdHISUQJf/5EFPUvIhFmD4xuxGDsOwpYjSmXPGyj 12 | /gKBKZhJ8+S7meR6Ssw3fhiFS1zGx0dKZjXn+naiW8qlMmPd7l9rYpWzBy/vsWwL 13 | XuAh8xeq83e0hM/6rUsskc0CAwEAAQ== 14 | -----END PUBLIC KEY----- 15 | -------------------------------------------------------------------------------- /test-resources/puppetserver/bootstrap-7.x.cfg: -------------------------------------------------------------------------------- 1 | puppetlabs.services.request-handler.request-handler-service/request-handler-service 2 | puppetlabs.services.jruby.jruby-puppet-service/jruby-puppet-pooled-service 3 | puppetlabs.services.jruby-pool-manager.jruby-pool-manager-service/jruby-pool-manager-service 4 | puppetlabs.services.puppet-profiler.puppet-profiler-service/puppet-profiler-service 5 | puppetlabs.trapperkeeper.services.webserver.jetty9-service/jetty9-service 6 | puppetlabs.trapperkeeper.services.webrouting.webrouting-service/webrouting-service 7 | puppetlabs.services.config.puppet-server-config-service/puppet-server-config-service 8 | puppetlabs.services.master.master-service/master-service 9 | puppetlabs.services.legacy-routes.legacy-routes-service/legacy-routes-service 10 | puppetlabs.services.puppet-admin.puppet-admin-service/puppet-admin-service 11 | puppetlabs.trapperkeeper.services.authorization.authorization-service/authorization-service 12 | puppetlabs.services.versioned-code-service.versioned-code-service/versioned-code-service 13 | puppetlabs.trapperkeeper.services.scheduler.scheduler-service/scheduler-service 14 | puppetlabs.trapperkeeper.services.status.status-service/status-service 15 | puppetlabs.trapperkeeper.services.metrics.metrics-service/metrics-service 16 | puppetlabs.services.jruby.jruby-metrics-service/jruby-metrics-service 17 | puppetlabs.trapperkeeper.services.watcher.filesystem-watch-service/filesystem-watch-service 18 | # To enable the CA service, leave the following line uncommented 19 | puppetlabs.services.ca.certificate-authority-service/certificate-authority-service 20 | # To disable the CA service, comment out the above line and uncomment the line below 21 | #puppetlabs.services.ca.certificate-authority-disabled-service/certificate-authority-disabled-service 22 | -------------------------------------------------------------------------------- /test-resources/puppetserver/bootstrap.cfg: -------------------------------------------------------------------------------- 1 | puppetlabs.services.request-handler.request-handler-service/request-handler-service 2 | puppetlabs.services.jruby.jruby-puppet-service/jruby-puppet-pooled-service 3 | puppetlabs.services.jruby-pool-manager.jruby-pool-manager-service/jruby-pool-manager-service 4 | puppetlabs.services.puppet-profiler.puppet-profiler-service/puppet-profiler-service 5 | puppetlabs.trapperkeeper.services.webserver.jetty10-service/jetty10-service 6 | puppetlabs.trapperkeeper.services.webrouting.webrouting-service/webrouting-service 7 | puppetlabs.services.config.puppet-server-config-service/puppet-server-config-service 8 | puppetlabs.services.master.master-service/master-service 9 | puppetlabs.services.legacy-routes.legacy-routes-service/legacy-routes-service 10 | puppetlabs.services.puppet-admin.puppet-admin-service/puppet-admin-service 11 | puppetlabs.trapperkeeper.services.authorization.authorization-service/authorization-service 12 | puppetlabs.services.versioned-code-service.versioned-code-service/versioned-code-service 13 | puppetlabs.trapperkeeper.services.scheduler.scheduler-service/scheduler-service 14 | puppetlabs.trapperkeeper.services.status.status-service/status-service 15 | puppetlabs.trapperkeeper.services.metrics.metrics-service/metrics-service 16 | puppetlabs.services.jruby.jruby-metrics-service/jruby-metrics-service 17 | puppetlabs.trapperkeeper.services.watcher.filesystem-watch-service/filesystem-watch-service 18 | # To enable the CA service, leave the following line uncommented 19 | puppetlabs.services.ca.certificate-authority-service/certificate-authority-service 20 | # To disable the CA service, comment out the above line and uncomment the line below 21 | #puppetlabs.services.ca.certificate-authority-disabled-service/certificate-authority-disabled-service 22 | -------------------------------------------------------------------------------- /test-resources/puppetserver/logback-dev.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d %-5p [%t] [%c{2}] %m%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /test-resources/puppetserver/puppet.conf: -------------------------------------------------------------------------------- 1 | [main] 2 | certname = localhost 3 | 4 | [agent] 5 | server = localhost 6 | 7 | [master] 8 | storeconfigs = true 9 | storeconfigs_backend = puppetdb 10 | reports = puppetdb 11 | autosign = true 12 | -------------------------------------------------------------------------------- /test-resources/puppetserver/request-logging-dev.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ./target/logs/puppetserver-access.log 4 | 5 | %h %l %u %user %date "%r" %s %b %h %a %localPort %D 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /test-resources/puppetserver/rich_data_environment.conf: -------------------------------------------------------------------------------- 1 | rich_data = true 2 | -------------------------------------------------------------------------------- /test-resources/puppetserver/rich_data_puppet.conf: -------------------------------------------------------------------------------- 1 | [main] 2 | rich_data = true 3 | -------------------------------------------------------------------------------- /test-resources/puppetserver/ssl/ca/ca_crl.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN X509 CRL----- 2 | MIICmTCBggIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBwZXQgQ0E6 3 | IGxvY2FsaG9zdBcNMjIwMjA4MjI0OTEyWhcNMzcwMjA1MjI0OTE0WqAvMC0wHwYD 4 | VR0jBBgwFoAUEvfpMG3GZMu3oJCQabI53zkxLlMwCgYDVR0UBAMCAQAwDQYJKoZI 5 | hvcNAQELBQADggIBALoLYLSlzz7b1uAJxKweRbu6DIJXSAVUiVQxQEAy+2Ojv+B+ 6 | VVNuR14zJ5Fz3/V3cc4d7f1ifzQZW329EWSVw4MJt8YsBhffOFS6h2/1mgTJjnxz 7 | N3Tn+rLJoqbPgyUbExGk0b+M0abhobi3ynJZ9H7YDXz5StX9AjdAkP10DuF9YHb7 8 | 5AJobZFw1GaNISyZM7cduVeTbFFDDCfxnLK759Clbb5PGsVbGONxBgXWwn7pqPMN 9 | ksacUIWWhouRJ7Bg/WQ7buQs4jbkf+a2fmDqmRnZ0+GByNbuCNzWRnjnfrKfTYJH 10 | hh3DcHTxNHLGSz2gvlHywzTNx/R0gGseljGGt2TB6XQ7u8jN+IFgC5vLXN27S05s 11 | 88fY9bP+yRC+P9HTRJ87AQlT789CXa/5B9Ml1+IsDdCdRWasq13sFtFNp08DwcH5 12 | l8venCzkJ6Pv4R+4RLTThEBFuQFNgRt46s4kFZQ8TTLYmAg8cE5/7kJMtaPSttLZ 13 | 1rdz/oSc5U44S8TF6sFeumozF0u/9RAK5+qt5PcSV3Ek4t3dAB7nTe3pJB7m7yrq 14 | p//HG/WdSXoh/hlT7ANKxyVAUfaIiK7BFiN2q+EMLQXX7PQa3jd1ps79wReEO8AY 15 | 6yyaLeVjBEgRBb+mIES08wuuyBDusuaIEL18h9T7TMC0JO8Luq4/5R3Mz5VU 16 | -----END X509 CRL----- 17 | -----BEGIN X509 CRL----- 18 | MIICozCBjAIBATANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDDB5QdXBwZXQgUm9v 19 | dCBDQTogOTFkNjIxMjRlNTg4NTMXDTIyMDIwODIyNDkxMloXDTM3MDIwNTIyNDkx 20 | M1qgLzAtMB8GA1UdIwQYMBaAFJVmUAVa4iPk3U5Jm56pygR6OYwSMAoGA1UdFAQD 21 | AgEAMA0GCSqGSIb3DQEBCwUAA4ICAQB/H9oLpxySjc6UqgsT4meJ2RmUV3/s0wGx 22 | rObEZww30QzV6hvD46A/o7tlhkkyXbiTL7K/5zeE/Ixf/ySestNp+X4c0cZKJ/yZ 23 | 6tsYOG52gTDIcAF1glvDkyZEjBAIlfwhHl2SaZr1mwWzhoB+y34L4vz7OGt4iTXL 24 | CUdZ3+zwX/+RcV1bS/WJNFiOEG0DOprSzIK5bzcwstJTfuF+Zb16SWKyadv3PQIJ 25 | Dh2aFImrKMQcCMx4ZIINiiot7hjXpnI1DtlFBaE9A2q1O6BhI8TWO1Gicoqy1fGY 26 | +3d7gjNUVKTZ4ia6gTJOsIvlf5ZDFfM1ruPB5izUJBISl9+b+D3k0k/QshmgNPk6 27 | Q0iP+UnI2zmNTESA1VyymN8e/HrB8xFK5+NKDO5k3vS3i0gK5zl+lB/e21AWYeOs 28 | at0XEtyf4TYuMfb4asgeEX7wR8hRy79zmasoL85UHWla1Q+z4ZLTtUQ/s0WuK13c 29 | BoDwyub98RXe1PRHdDNwb0qnCpsaxHzYYewoNH0WOJ2/twb60JGocXge57+Pxlw0 30 | Vh2x59RElisCz6+TOxI2DUfxHmCya3245PZK+G0sD3qtSPiK+C/w9SRlHhnFXM0f 31 | xw0tja5Yk+UpGVZMcqrNzvQuRuNdKTcn7aZPnwpd98+aryoC/RmdtiUhHQAgz+bq 32 | gjo4Vg5ykw== 33 | -----END X509 CRL----- 34 | -------------------------------------------------------------------------------- /test-resources/puppetserver/ssl/ca/ca_pub.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwVM0mdVROZaeKC9BSKkk 3 | GiqKnO/HpPHjdj4ZVcGHXd9ypmfzOSskPQ8mTCwa4R0rMgzhHB7KXN3QX0Cn4jMl 4 | /zWxujmYHy+a69anou4OPRJSATAUvxLb3acxKTEeDpH4WrK/e5vImFYsLRMgDoYx 5 | iTPD0OjeD/DcVY+tXSbSO4TP9cYQPA7bETjCFRSi2Ww92/umk/eXFYyzQkRt9/u4 6 | YObMZTVPcQUpeTruKyzucA3gaejdOb/dLpuKAFBn9LuJW1VfwMMbhPcdHJ7jYWl3 7 | 0wIyyefZrc2au005MBvi0KIaJ7xbuNm7hZVT+CveGDeRRqSGLZ44k/6obv/hU3uY 8 | F776E6McRhCoZLUpze2iv9BI6VVAu8viErlxTnyzX2xFci0Uf/UklzPm5cdzqYEN 9 | d/YJExnwsy0eY5OE9Ya644REgXAjAPp2WnUjvk/fxBUHjiIqNtD3PE1PtFUbdNLh 10 | 1EQ9GLSBDrzRsPLM9VXMPJBsVrMPfB2yGkAOPFkqOE+XSIa/UyO00pVtVQBfJX8c 11 | NmquczHQe+KJ5OPmCP2MTJY2zSH/NzwWs1TSQaK0mkdtlaNAKzYoCPnDWNeHHONw 12 | 9bRO9qusc06Q1B4JLCvbyYAHRbe+elsTUE87Hy2vT0xkooWh4gEn3MFFN8mpdys8 13 | J1h0vxakklDBq0zUF9dJc8cCAwEAAQ== 14 | -----END PUBLIC KEY----- 15 | -------------------------------------------------------------------------------- /test-resources/puppetserver/ssl/ca/inventory.txt: -------------------------------------------------------------------------------- 1 | 0x0001 2022-02-08T22:49:12UTC 2037-02-05T22:49:14UTC /CN=localhost 2 | -------------------------------------------------------------------------------- /test-resources/puppetserver/ssl/ca/serial: -------------------------------------------------------------------------------- 1 | 002 2 | -------------------------------------------------------------------------------- /test-resources/puppetserver/ssl/ca/signed/localhost.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFmjCCA4KgAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw 3 | ZXQgQ0E6IGxvY2FsaG9zdDAeFw0yMjAyMDgyMjQ5MTJaFw0zNzAyMDUyMjQ5MTRa 4 | MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC 5 | AgoCggIBALQWsayBs2PuA8ML3zxtveuqMc439r3UTkIEXlHrGP1zLuiuKKnRMe0L 6 | 7e0vITp5H0bzhHpDzUh/Sj2zwdCveqk8/wCk1YhUhM3TRHCjwwD4y1ELNQfJGOMp 7 | ntsurcidlFZfTMm/MTv+96O1kX3dJiLZBajeA0NmPo69T5ndWkGTlMtUKkHkoG6X 8 | xEwLtg1YEFHeolv8HALzuvtDKiS+/exbuwtOsNJ03tuPyBVNixGN8bgL/0VgKe2i 9 | UaB0c4s6EyGqHXh1ISQfxkkiQKlyn0ihod2+kUonSFbnD7dqL/f5VvedIgTqsymK 10 | 8US1E8neJZVvguE2xLejDSg3YYGxU6RnOrjyj4lVqakfMlIl4xOA23ik4H9LEWwz 11 | ZZ2FT8p5bNHxi2iu4iSCN5OoqdOC7dc3+qqe7lsff61db+0ntck4PBYz6d9SkPF6 12 | i1Si4OdAnqRhS2gns9c4Xjb1iI4WZ16B3zSNWM92n+nFV4c6QluSRq4nWwmT2wLD 13 | e2XLycHwe2qOFSJCJxEjfActdrqx0Bhl5OFYoNxuMVT0FK4cdphjDKdO5XiyfQgA 14 | wUiUcp6YmWE5fG0GzyCGjwl2OeVl+4fVDuZ5zLyqdL1BWmhXdwTB9kQYTQBPdMqp 15 | 5HH9g2WgBda8U+VOXA4QM9Jt6RNCNJWh4VLIo4DEireTARfMHdljAgMBAAGjgesw 16 | gegwDAYDVR0TAQH/BAIwADAxBglghkgBhvhCAQ0EJBYiUHVwcGV0IFNlcnZlciBJ 17 | bnRlcm5hbCBDZXJ0aWZpY2F0ZTAfBgNVHSMEGDAWgBQS9+kwbcZky7egkJBpsjnf 18 | OTEuUzAgBgNVHSUBAf8EFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYDVR0PAQH/ 19 | BAQDAgWgMB0GA1UdDgQWBBSQWFEuHHH7DaaBoSOjRijaSmcGsTAVBgsrBgEEAYKM 20 | TAEDJwQGDAR0cnVlMBwGA1UdEQQVMBOCBnB1cHBldIIJbG9jYWxob3N0MA0GCSqG 21 | SIb3DQEBCwUAA4ICAQAehauayF0L+E/l2Nts0QH4vlEJjQIUdB1Zc7l7dqSetANB 22 | vfB/erwBHRmi061Daadm4R9P40g1gKkAYP4vF4JTc31UI4dUtFyXWKzXjQYbG7wg 23 | 25L7ioj0Y0mOamGIK/am2b6v56OgAhv9CxCAM7NG+uotLomgmcKS2ROiWH/kfNIU 24 | YKgO/PkEJsY3G2gCPpnYkzxXsYZxSAnb4++O9WE0OoNS42PZ9mKGMLlTneANkFeB 25 | Pq+85Po1DlOFs7l9yhrieC3MmUXzqahah53MhBv2Ap6qm4+AQq1NiP6Kyh9Pp1yV 26 | 6aPxR0+b5tWLtd7oeSBbBTHYEz3ToLbzdXbjDnAvBikQI6W/ff7ffi3g8Zb/ZJZy 27 | n9DZAU7zpNS8F0m6Ejfcpxjbi4exJHxk9F527W/rT1Rzal1Qr4faY5U9lCLJthg0 28 | 6VX9rGVv16IJnabRWyRUcWLwVsYZfvieAnhbFZFMWyI0b22eqRzVqDHgTJzVfMhJ 29 | GRfUJ5Wcw0YQyNgvp/dhAgNHzcxz/bMW7dAZjDAJuadw2elK3cH2BkbGeJiPZoYn 30 | RP+8scFvl4iEPcWEOYW3Wu8/JF0ccXj4xKUCBh3WOwe4JIQ+sidqN9GxH1bIuquP 31 | 7gXLl/QjRQIh2NBh3pXdUgzb3VL2G9y0s91GlrgbtpiS+8XboVPMe/K/1xSokQ== 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /test-resources/puppetserver/ssl/certs/localhost.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFmjCCA4KgAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBw 3 | ZXQgQ0E6IGxvY2FsaG9zdDAeFw0yMjAyMDgyMjQ5MTJaFw0zNzAyMDUyMjQ5MTRa 4 | MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC 5 | AgoCggIBALQWsayBs2PuA8ML3zxtveuqMc439r3UTkIEXlHrGP1zLuiuKKnRMe0L 6 | 7e0vITp5H0bzhHpDzUh/Sj2zwdCveqk8/wCk1YhUhM3TRHCjwwD4y1ELNQfJGOMp 7 | ntsurcidlFZfTMm/MTv+96O1kX3dJiLZBajeA0NmPo69T5ndWkGTlMtUKkHkoG6X 8 | xEwLtg1YEFHeolv8HALzuvtDKiS+/exbuwtOsNJ03tuPyBVNixGN8bgL/0VgKe2i 9 | UaB0c4s6EyGqHXh1ISQfxkkiQKlyn0ihod2+kUonSFbnD7dqL/f5VvedIgTqsymK 10 | 8US1E8neJZVvguE2xLejDSg3YYGxU6RnOrjyj4lVqakfMlIl4xOA23ik4H9LEWwz 11 | ZZ2FT8p5bNHxi2iu4iSCN5OoqdOC7dc3+qqe7lsff61db+0ntck4PBYz6d9SkPF6 12 | i1Si4OdAnqRhS2gns9c4Xjb1iI4WZ16B3zSNWM92n+nFV4c6QluSRq4nWwmT2wLD 13 | e2XLycHwe2qOFSJCJxEjfActdrqx0Bhl5OFYoNxuMVT0FK4cdphjDKdO5XiyfQgA 14 | wUiUcp6YmWE5fG0GzyCGjwl2OeVl+4fVDuZ5zLyqdL1BWmhXdwTB9kQYTQBPdMqp 15 | 5HH9g2WgBda8U+VOXA4QM9Jt6RNCNJWh4VLIo4DEireTARfMHdljAgMBAAGjgesw 16 | gegwDAYDVR0TAQH/BAIwADAxBglghkgBhvhCAQ0EJBYiUHVwcGV0IFNlcnZlciBJ 17 | bnRlcm5hbCBDZXJ0aWZpY2F0ZTAfBgNVHSMEGDAWgBQS9+kwbcZky7egkJBpsjnf 18 | OTEuUzAgBgNVHSUBAf8EFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYDVR0PAQH/ 19 | BAQDAgWgMB0GA1UdDgQWBBSQWFEuHHH7DaaBoSOjRijaSmcGsTAVBgsrBgEEAYKM 20 | TAEDJwQGDAR0cnVlMBwGA1UdEQQVMBOCBnB1cHBldIIJbG9jYWxob3N0MA0GCSqG 21 | SIb3DQEBCwUAA4ICAQAehauayF0L+E/l2Nts0QH4vlEJjQIUdB1Zc7l7dqSetANB 22 | vfB/erwBHRmi061Daadm4R9P40g1gKkAYP4vF4JTc31UI4dUtFyXWKzXjQYbG7wg 23 | 25L7ioj0Y0mOamGIK/am2b6v56OgAhv9CxCAM7NG+uotLomgmcKS2ROiWH/kfNIU 24 | YKgO/PkEJsY3G2gCPpnYkzxXsYZxSAnb4++O9WE0OoNS42PZ9mKGMLlTneANkFeB 25 | Pq+85Po1DlOFs7l9yhrieC3MmUXzqahah53MhBv2Ap6qm4+AQq1NiP6Kyh9Pp1yV 26 | 6aPxR0+b5tWLtd7oeSBbBTHYEz3ToLbzdXbjDnAvBikQI6W/ff7ffi3g8Zb/ZJZy 27 | n9DZAU7zpNS8F0m6Ejfcpxjbi4exJHxk9F527W/rT1Rzal1Qr4faY5U9lCLJthg0 28 | 6VX9rGVv16IJnabRWyRUcWLwVsYZfvieAnhbFZFMWyI0b22eqRzVqDHgTJzVfMhJ 29 | GRfUJ5Wcw0YQyNgvp/dhAgNHzcxz/bMW7dAZjDAJuadw2elK3cH2BkbGeJiPZoYn 30 | RP+8scFvl4iEPcWEOYW3Wu8/JF0ccXj4xKUCBh3WOwe4JIQ+sidqN9GxH1bIuquP 31 | 7gXLl/QjRQIh2NBh3pXdUgzb3VL2G9y0s91GlrgbtpiS+8XboVPMe/K/1xSokQ== 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /test-resources/puppetserver/ssl/crl.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN X509 CRL----- 2 | MIICmTCBggIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRQdXBwZXQgQ0E6 3 | IGxvY2FsaG9zdBcNMjIwMjA4MjI0OTEyWhcNMzcwMjA1MjI0OTE0WqAvMC0wHwYD 4 | VR0jBBgwFoAUEvfpMG3GZMu3oJCQabI53zkxLlMwCgYDVR0UBAMCAQAwDQYJKoZI 5 | hvcNAQELBQADggIBALoLYLSlzz7b1uAJxKweRbu6DIJXSAVUiVQxQEAy+2Ojv+B+ 6 | VVNuR14zJ5Fz3/V3cc4d7f1ifzQZW329EWSVw4MJt8YsBhffOFS6h2/1mgTJjnxz 7 | N3Tn+rLJoqbPgyUbExGk0b+M0abhobi3ynJZ9H7YDXz5StX9AjdAkP10DuF9YHb7 8 | 5AJobZFw1GaNISyZM7cduVeTbFFDDCfxnLK759Clbb5PGsVbGONxBgXWwn7pqPMN 9 | ksacUIWWhouRJ7Bg/WQ7buQs4jbkf+a2fmDqmRnZ0+GByNbuCNzWRnjnfrKfTYJH 10 | hh3DcHTxNHLGSz2gvlHywzTNx/R0gGseljGGt2TB6XQ7u8jN+IFgC5vLXN27S05s 11 | 88fY9bP+yRC+P9HTRJ87AQlT789CXa/5B9Ml1+IsDdCdRWasq13sFtFNp08DwcH5 12 | l8venCzkJ6Pv4R+4RLTThEBFuQFNgRt46s4kFZQ8TTLYmAg8cE5/7kJMtaPSttLZ 13 | 1rdz/oSc5U44S8TF6sFeumozF0u/9RAK5+qt5PcSV3Ek4t3dAB7nTe3pJB7m7yrq 14 | p//HG/WdSXoh/hlT7ANKxyVAUfaIiK7BFiN2q+EMLQXX7PQa3jd1ps79wReEO8AY 15 | 6yyaLeVjBEgRBb+mIES08wuuyBDusuaIEL18h9T7TMC0JO8Luq4/5R3Mz5VU 16 | -----END X509 CRL----- 17 | -----BEGIN X509 CRL----- 18 | MIICozCBjAIBATANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDDB5QdXBwZXQgUm9v 19 | dCBDQTogOTFkNjIxMjRlNTg4NTMXDTIyMDIwODIyNDkxMloXDTM3MDIwNTIyNDkx 20 | M1qgLzAtMB8GA1UdIwQYMBaAFJVmUAVa4iPk3U5Jm56pygR6OYwSMAoGA1UdFAQD 21 | AgEAMA0GCSqGSIb3DQEBCwUAA4ICAQB/H9oLpxySjc6UqgsT4meJ2RmUV3/s0wGx 22 | rObEZww30QzV6hvD46A/o7tlhkkyXbiTL7K/5zeE/Ixf/ySestNp+X4c0cZKJ/yZ 23 | 6tsYOG52gTDIcAF1glvDkyZEjBAIlfwhHl2SaZr1mwWzhoB+y34L4vz7OGt4iTXL 24 | CUdZ3+zwX/+RcV1bS/WJNFiOEG0DOprSzIK5bzcwstJTfuF+Zb16SWKyadv3PQIJ 25 | Dh2aFImrKMQcCMx4ZIINiiot7hjXpnI1DtlFBaE9A2q1O6BhI8TWO1Gicoqy1fGY 26 | +3d7gjNUVKTZ4ia6gTJOsIvlf5ZDFfM1ruPB5izUJBISl9+b+D3k0k/QshmgNPk6 27 | Q0iP+UnI2zmNTESA1VyymN8e/HrB8xFK5+NKDO5k3vS3i0gK5zl+lB/e21AWYeOs 28 | at0XEtyf4TYuMfb4asgeEX7wR8hRy79zmasoL85UHWla1Q+z4ZLTtUQ/s0WuK13c 29 | BoDwyub98RXe1PRHdDNwb0qnCpsaxHzYYewoNH0WOJ2/twb60JGocXge57+Pxlw0 30 | Vh2x59RElisCz6+TOxI2DUfxHmCya3245PZK+G0sD3qtSPiK+C/w9SRlHhnFXM0f 31 | xw0tja5Yk+UpGVZMcqrNzvQuRuNdKTcn7aZPnwpd98+aryoC/RmdtiUhHQAgz+bq 32 | gjo4Vg5ykw== 33 | -----END X509 CRL----- 34 | -------------------------------------------------------------------------------- /test-resources/puppetserver/ssl/public_keys/localhost.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtBaxrIGzY+4DwwvfPG29 3 | 66oxzjf2vdROQgReUesY/XMu6K4oqdEx7Qvt7S8hOnkfRvOEekPNSH9KPbPB0K96 4 | qTz/AKTViFSEzdNEcKPDAPjLUQs1B8kY4yme2y6tyJ2UVl9Myb8xO/73o7WRfd0m 5 | ItkFqN4DQ2Y+jr1Pmd1aQZOUy1QqQeSgbpfETAu2DVgQUd6iW/wcAvO6+0MqJL79 6 | 7Fu7C06w0nTe24/IFU2LEY3xuAv/RWAp7aJRoHRzizoTIaodeHUhJB/GSSJAqXKf 7 | SKGh3b6RSidIVucPt2ov9/lW950iBOqzKYrxRLUTyd4llW+C4TbEt6MNKDdhgbFT 8 | pGc6uPKPiVWpqR8yUiXjE4DbeKTgf0sRbDNlnYVPynls0fGLaK7iJII3k6ip04Lt 9 | 1zf6qp7uWx9/rV1v7Se1yTg8FjPp31KQ8XqLVKLg50CepGFLaCez1zheNvWIjhZn 10 | XoHfNI1Yz3af6cVXhzpCW5JGridbCZPbAsN7ZcvJwfB7ao4VIkInESN8By12urHQ 11 | GGXk4Vig3G4xVPQUrhx2mGMMp07leLJ9CADBSJRynpiZYTl8bQbPIIaPCXY55WX7 12 | h9UO5nnMvKp0vUFaaFd3BMH2RBhNAE90yqnkcf2DZaAF1rxT5U5cDhAz0m3pE0I0 13 | laHhUsijgMSKt5MBF8wd2WMCAwEAAQ== 14 | -----END PUBLIC KEY----- 15 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/archive_test.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.archive-test 2 | (:import [java.io ByteArrayOutputStream ByteArrayInputStream]) 3 | (:require [puppetlabs.puppetdb.archive :as archive] 4 | [clojure.java.io :as io] 5 | [clojure.test :refer :all])) 6 | 7 | (deftest test-tar-read-write 8 | (let [bazfile { :path (.getPath (io/file "foo" "bar" "baz.txt")) 9 | :content "This is a test" } 10 | blingfile { :path (.getPath (io/file "foo" "blah" "bling.txt")) 11 | :content "This is another test" } 12 | tar-entries { (:path bazfile) (:content bazfile) 13 | (:path blingfile) (:content blingfile) } 14 | out-stream (ByteArrayOutputStream.)] 15 | (testing "should be able to write a simple tarball w/o errors" 16 | (with-open [tar-writer (archive/tarball-writer out-stream)] 17 | (archive/add-entry tar-writer "UTF-8" (:path bazfile) (:content bazfile)) 18 | (archive/add-entry tar-writer "UTF-8" (:path blingfile) (:content blingfile)))) 19 | 20 | (with-open [in-stream (ByteArrayInputStream. (.toByteArray out-stream))] 21 | (with-open [tar-reader (archive/tarball-reader in-stream)] 22 | (testing "should be able to find a specific entry in a tarball" 23 | (let [bling-entry (archive/find-entry tar-reader (:path blingfile))] 24 | (is (not (nil? bling-entry))) 25 | (is (= (:content blingfile) (archive/read-entry-content tar-reader))))))) 26 | 27 | (with-open [in-stream (ByteArrayInputStream. (.toByteArray out-stream))] 28 | (with-open [tar-reader (archive/tarball-reader in-stream)] 29 | (let [entry-count (atom 0)] 30 | (testing "should only contain the expected entries, with expected content" 31 | (doseq [tar-entry (archive/all-entries tar-reader)] 32 | (swap! entry-count inc) 33 | (is (contains? tar-entries (.getName tar-entry))) 34 | (let [content (archive/read-entry-content tar-reader)] 35 | (is (= content (tar-entries (.getName tar-entry))))))) 36 | 37 | (testing "should contain the correct number of entries" 38 | (is (= (count tar-entries) @entry-count)))))))) 39 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/cli/pdb_dataset_test.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.cli.pdb-dataset-test 2 | (:require 3 | [clojure.test :refer [deftest is testing]] 4 | [puppetlabs.puppetdb.cli.pdb-dataset :refer [validate-cli!]] 5 | [puppetlabs.puppetdb.utils :as utils :refer [with-captured-throw]] 6 | [clojure.string :as str] 7 | [puppetlabs.kitchensink.core :as kitchensink]) 8 | (:import 9 | [clojure.lang ExceptionInfo])) 10 | 11 | (defn dataset 12 | [& args] 13 | (with-redefs [utils/try-process-cli (fn [body] (body))] 14 | (validate-cli! args))) 15 | 16 | (deftest returned-error 17 | (testing "when required input parameter is missing" 18 | (let [response (with-captured-throw (dataset))] 19 | (is (= ExceptionInfo (class response))) 20 | (when (= ExceptionInfo (class response)) 21 | (is (= ::kitchensink/cli-error (:kind (ex-data response)))) 22 | (is (str/includes? (:msg (ex-data response)) 23 | "Missing required argument '--dumpfile'!"))))) 24 | 25 | (testing "when provided data is invalid" 26 | (let [response (with-captured-throw (dataset "-t" "invalid-date" "-d" "dumpfile"))] 27 | (is (= ExceptionInfo (class response))) 28 | (when (= ExceptionInfo (class response)) 29 | (is (= ::kitchensink/cli-error (:kind (ex-data response)))) 30 | (is (str/includes? (:msg (ex-data response)) 31 | "Error: time shift date must be in UTC format!")))))) 32 | 33 | (deftest correct-usage 34 | (testing "when the time shift date is provided" 35 | (let [response (dataset "-t" "2021-04-14T18:56" "-d" "dumpfile")] 36 | (is (= {:dumpfile "dumpfile" 37 | :timeshift-to #inst "2021-04-14T18:56:00.000000000-00:00"} response))))) 38 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/cli/time_shift_export_test.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.cli.time-shift-export-test 2 | (:require 3 | [clojure.test :refer [deftest is testing]] 4 | [puppetlabs.puppetdb.cli.time-shift-export :refer [time-shift-export-wrapper, file-exists?]] 5 | [puppetlabs.puppetdb.utils :as utils :refer [with-captured-throw]] 6 | [clojure.string :as str] 7 | [puppetlabs.kitchensink.core :as kitchensink]) 8 | (:import 9 | [clojure.lang ExceptionInfo])) 10 | 11 | (defn time-shift 12 | [& args] 13 | (with-redefs [utils/try-process-cli (fn [body] (body))] 14 | (time-shift-export-wrapper args))) 15 | 16 | (deftest returned-error 17 | (testing "when required input parameter is missing" 18 | (let [response (with-captured-throw (time-shift))] 19 | (is (= ExceptionInfo (class response))) 20 | (when (= ExceptionInfo (class response)) 21 | (is (= ::kitchensink/cli-error (:kind (ex-data response)))) 22 | (is (str/includes? (:msg (ex-data response)) 23 | "Missing required argument '--input'!"))))) 24 | 25 | (testing "when required input parameter is invalid" 26 | (with-redefs [file-exists? (fn [_] false)] 27 | (let [response (with-captured-throw (time-shift "-i" "/path/archive"))] 28 | (is (= ExceptionInfo (class response))) 29 | (when (= ExceptionInfo (class response)) 30 | (is (= ::kitchensink/cli-error (:kind (ex-data response)))) 31 | (is (str/includes? (:msg (ex-data response)) 32 | "Error: input archive path: /path/archive, must be valid!")))))) 33 | 34 | (testing "when provided data is invalid" 35 | (with-redefs [file-exists? (fn [_] true)] 36 | (let [response (with-captured-throw (time-shift "-i" "/path/archive" "-t" "invalid-date"))] 37 | (is (= ExceptionInfo (class response))) 38 | (when (= ExceptionInfo (class response)) 39 | (is (= ::kitchensink/cli-error (:kind (ex-data response)))) 40 | (is (str/includes? (:msg (ex-data response)) 41 | "Error: time shift date: invalid-date, must be in UTC format!"))))))) 42 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/cli/util_test.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.cli.util-test 2 | (:require 3 | [clojure.test :refer [deftest is]] 4 | [puppetlabs.puppetdb.cli.util :refer [jdk-support-status]])) 5 | 6 | (deftest jdk-support-status-behavior 7 | (is (= :no (jdk-support-status "1.5"))) 8 | (is (= :no (jdk-support-status "1.5.0"))) 9 | (is (= :no (jdk-support-status "1.6"))) 10 | (is (= :no (jdk-support-status "1.6.0"))) 11 | (is (= :unknown (jdk-support-status "1.60"))) 12 | (is (= :unknown (jdk-support-status "1.60.1"))) 13 | (is (= :unknown (jdk-support-status "huh?"))) 14 | (is (= :no (jdk-support-status "1.7"))) 15 | (is (= :no (jdk-support-status "1.7.0"))) 16 | (is (= :deprecated (jdk-support-status "1.8"))) 17 | (is (= :deprecated (jdk-support-status "1.8.0"))) 18 | (is (= :deprecated (jdk-support-status "1.9"))) 19 | (is (= :deprecated (jdk-support-status "1.9.0"))) 20 | (is (= :deprecated (jdk-support-status "10"))) 21 | (is (= :deprecated (jdk-support-status "10.0"))) 22 | (is (= :tested (jdk-support-status "11.0"))) 23 | (is (= :tested (jdk-support-status "11.0.7"))) 24 | (is (= :official (jdk-support-status "17.0.4")))) 25 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/core_test.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.core-test 2 | (:require 3 | [clojure.test :refer :all] 4 | [puppetlabs.puppetdb.cli.util :as cliu] 5 | [puppetlabs.puppetdb.core :as core] 6 | [puppetlabs.trapperkeeper.logging :refer [root-logger]] 7 | [puppetlabs.trapperkeeper.testutils.logging 8 | :refer [with-log-level with-logged-event-maps]])) 9 | 10 | (deftest handling-of-invalid-jdk-versions 11 | (let [logs? #{"services" "upgrade"}] 12 | (letfn [(check [subcommand version] 13 | (let [err (java.io.StringWriter.) 14 | [result err log] 15 | (binding [*err* err] 16 | (with-log-level (root-logger) :error 17 | (with-logged-event-maps log 18 | ;; Relies on clj's left-to-right arg eval order 19 | [(with-redefs [cliu/java-version (constantly version)] 20 | (core/run-subcommand subcommand [])) 21 | (str err) @log])))] 22 | (is (= cliu/err-exit-status result)) 23 | ;; Right now the output may also include clojure warning lines 24 | (is (re-find #"(?s)(?:^|\n)error: PuppetDB doesn't support.*" err)) 25 | (if-not (logs? subcommand) 26 | (is (= [] log)) 27 | (do 28 | (is (= 1 (count log))) 29 | (let [[{:keys [logger level message]}] log] 30 | (is (= "puppetlabs.puppetdb.cli.tk-util" logger)) 31 | (is (= :error level)) 32 | (is (re-find #"PuppetDB doesn't support.*" message)))))))] 33 | (doseq [cmd ["help" "version" "benchmark" "services" "upgrade"]] 34 | (check cmd "1.5.0"))))) 35 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/dashboard_test.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.dashboard-test 2 | (:require [puppetlabs.puppetdb.dashboard 3 | :refer [build-app dashboard-routes default-meter-defs]] 4 | [puppetlabs.puppetdb.http :as http] 5 | [clojure.test :refer :all] 6 | [ring.mock.request :refer [request]] 7 | [puppetlabs.puppetdb.testutils.services :as svc-utils] 8 | [puppetlabs.puppetdb.utils :refer [base-url->str-with-prefix]] 9 | [puppetlabs.puppetdb.testutils :as tu] 10 | [puppetlabs.puppetdb.testutils.dashboard :as dtu] 11 | [puppetlabs.puppetdb.middleware :as mid] 12 | [puppetlabs.puppetdb.cheshire :as json])) 13 | 14 | (deftest dashboard-resource-requests 15 | (testing "dashboard redirect works" 16 | (let [handler (mid/make-pdb-handler dashboard-routes) 17 | {:keys [status headers]} (handler (request :get "/"))] 18 | (is (= status 302)) 19 | (is (= "/pdb/dashboard/index.html" (get headers "Location"))))) 20 | (testing "dashboard data request works" 21 | (let [handler (build-app default-meter-defs) 22 | {:keys [status body]} (handler (request :get "/data")) 23 | body (json/parse-string body true)] 24 | (is (= status 200)) 25 | (is (seq? body)) 26 | (is (= (count body) 27 | (->> body (map :id) distinct count)))))) 28 | 29 | (deftest dashboard-routing 30 | (svc-utils/call-with-single-quiet-pdb-instance 31 | (fn [] 32 | (let [root-resp (svc-utils/get-unparsed (svc-utils/root-url-str))] 33 | (tu/assert-success! root-resp) 34 | (is (dtu/dashboard-page? root-resp))) 35 | 36 | (let [data-resp (-> svc-utils/*base-url* 37 | (assoc :prefix "/pdb/dashboard/data") 38 | base-url->str-with-prefix 39 | svc-utils/get-unparsed)] 40 | (tu/assert-success! data-resp) 41 | (is (http/json-utf8-ctype? (get-in data-resp [:headers "content-type"]) )) 42 | (is (seq? (json/parse-string (:body data-resp) true))))))) 43 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/generative/overrideable_generators_test.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.generative.overrideable-generators-test 2 | (:require [clojure.test :refer :all] 3 | [clojure.test.check.clojure-test :as tc] 4 | [clojure.test.check.properties :as prop] 5 | [puppetlabs.puppetdb.generative.overridable-generators :as ogen])) 6 | 7 | (ogen/defgen :test/a ogen/boolean) 8 | (ogen/defgen :test/b ogen/uuid) 9 | (ogen/defgen :test/map (ogen/keys :test/a :test/b)) 10 | 11 | (tc/defspec keys-generator 100 12 | (prop/for-all [m (ogen/convert :test/map)] 13 | (is (= [:a :b] (keys m))))) 14 | 15 | (tc/defspec overrides 100 16 | (prop/for-all [m (->> :test/map 17 | (ogen/override {:test/a (ogen/return true)}) 18 | ogen/convert)] 19 | (is (= [:a :b] (clojure.core/keys m))) 20 | (is (= true (:a m))))) 21 | 22 | (tc/defspec override-presedence-is-outside-in 100 23 | (prop/for-all [m (->> :test/map 24 | (ogen/override {:test/a (ogen/return true)}) 25 | (ogen/override {:test/a (ogen/return false)}) 26 | ogen/convert)] 27 | (is (= [:a :b] (clojure.core/keys m))) 28 | (is (= false (:a m))))) 29 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/http/query_test.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.http.query-test 2 | (:require [puppetlabs.puppetdb.http.query :as sut] 3 | [clojure.test :as t])) 4 | 5 | (t/deftest add-criteria-test 6 | (t/are [query criteria result] 7 | (= result (sut/add-criteria criteria query)) 8 | ["=" "bar" 7] ["=" "foo" 42] 9 | ["and" ["=" "bar" 7] ["=" "foo" 42]] 10 | 11 | ["extract" ["foo" "bar"]] nil 12 | ["extract" ["foo" "bar"]] 13 | 14 | ["extract" ["foo" "bar"]] ["=" "foo" 42] 15 | ["extract" ["foo" "bar"] ["=" "foo" 42]] 16 | 17 | ["extract" ["foo" "bar"] nil] ["=" "foo" 42] 18 | ["extract" ["foo" "bar"] ["=" "foo" 42]] 19 | 20 | ["extract" ["foo" "bar"] ["=" "bar" 7]] ["=" "foo" 42] 21 | ["extract" ["foo" "bar"] ["and" ["=" "bar" 7] ["=" "foo" 42]]] 22 | 23 | ["from" "thing" ["extract" ["foo" "bar"] ["=" "bar" 7]]] ["=" "foo" 42] 24 | ["from" "thing" ["extract" ["foo" "bar"] ["and" ["=" "bar" 7] ["=" "foo" 42]]]] 25 | 26 | ["from" "thing"] ["=" "foo" 42] 27 | ["from" "thing" ["=" "foo" 42]])) 28 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/http/sync_version_checking.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.http.sync-version-checking 2 | (:require [clojure.test :refer :all] 3 | [puppetlabs.puppetdb.constants :as constants] 4 | [puppetlabs.puppetdb.http :as http] 5 | [puppetlabs.puppetdb.testutils.http 6 | :refer [deftest-http-app query-response *app*]] 7 | [puppetlabs.puppetdb.testutils :refer [query-request]])) 8 | 9 | (def endpoints [[:v4 "/v4"]]) 10 | 11 | (deftest-http-app sync-version-checking-headers 12 | [[_version endpoint] endpoints 13 | method [:get :post]] 14 | (let [req-with-sync-ver (fn [ver] 15 | (*app* 16 | (query-request 17 | method endpoint 18 | ["from" "nodes"] 19 | {:headers {"x-pdb-sync-ver" ver}}))) 20 | sync-ver constants/pdb-sync-ver] 21 | 22 | (testing "should succeed when sync versions are equal" 23 | (is (= 200 (:status (req-with-sync-ver (str sync-ver)))))) 24 | 25 | (testing "should succed when sync version missing" 26 | (is (= 200 (:status (query-response method endpoint ["from" "nodes"]))))) 27 | 28 | (testing "should fail when sync versions mismatched" 29 | (is (= (req-with-sync-ver (str (inc sync-ver))) 30 | {:status 409 31 | :headers {"Content-Type" http/error-response-content-type} 32 | :body "PDB sync request version 3 too new for this server (expected 2)."}))) 33 | 34 | (testing "should fail when x-pdb-sync-ver input is invalid" 35 | (is (= (req-with-sync-ver "abc") 36 | {:status 400 37 | :headers {"Content-Type" http/error-response-content-type} 38 | :body 39 | "The x-pdb-sync-ver header: abc cannot be converted to an int."}))))) 40 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/integration/file_with_binary_template.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.integration.file-with-binary-template 2 | (:require 3 | [clojure.test :refer :all] 4 | [clojure.string :as str] 5 | [me.raynes.fs :as fs] 6 | [puppetlabs.puppetdb.integration.fixtures :as int])) 7 | 8 | (deftest ^:integration file-with-binary-template 9 | ;; Puppet 8 removes the ability to serialize binary files without using the 10 | ;; rich data type Binary, or installing the puppet-pson gem 11 | (when (< 8 12 | (->> (int/bundle-exec {} "puppet" "--version") 13 | :out 14 | str/trim-newline 15 | (re-matches #"^(\d+).*") 16 | second 17 | (Integer/parseInt))) 18 | (with-open [pg (int/setup-postgres) 19 | pdb (int/run-puppetdb pg {}) 20 | ps (int/run-puppet-server [pdb] {})] 21 | 22 | (let [temp-dir (fs/temp-dir "file-with-binary-template") 23 | file-resource-path (str temp-dir "/binary-file") 24 | binary-template-path (fs/absolute "test-resources/binary-template.erb")] 25 | 26 | (testing "Run puppet with a binary template" 27 | (int/run-puppet ps pdb 28 | (str "file { '" file-resource-path "':" 29 | " content => template('" binary-template-path "')," 30 | " tag => 'binary_file'," 31 | "}") 32 | {:certname "binary-file-agent" 33 | ;; this is a workaround for puppet's present inability to automatically 34 | ;; downgrade from json to pson; it will be removed once 35 | ;; that feature is added. 36 | :extra-puppet-args ["--preferred_serialization_format" "pson"]})) 37 | 38 | (testing "PDB should have stored the resource" 39 | (is (= {:certname "binary-file-agent" 40 | :type "File" 41 | :title file-resource-path} 42 | (first (int/pql-query pdb "resources [certname, type, title] { tag = 'binary_file' }"))))))))) 43 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/integration/masterless.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.integration.masterless 2 | (:require 3 | [clojure.test :refer :all] 4 | [puppetlabs.puppetdb.integration.fixtures :as int])) 5 | 6 | (deftest ^:integration masterless-fact-storage 7 | (with-open [pg (int/setup-postgres) 8 | pdb (int/run-puppetdb pg {})] 9 | (testing "Run puppet apply to populate the db" 10 | (let [{:keys [out]} (int/run-puppet-apply pdb "notice($foo)" 11 | {:env {"FACTER_foo" "testfoo"}})] 12 | (is (re-find #"testfoo" out)))) 13 | 14 | (testing "Run again to ensure we aren't using puppetdb for the answer" 15 | (let [{:keys [out]} (int/run-puppet-apply pdb "notice($foo)" 16 | {:env {"FACTER_foo" "second test"}})] 17 | (is (re-find #"second test" out)))) 18 | 19 | (testing "Check that the fact was put in puppetdb" 20 | (is (= [{:value "second test"}] (int/pql-query pdb "facts [value] { name='foo' }")))))) 21 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/integration/terminus_failover.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.integration.terminus-failover 2 | (:require 3 | [clojure.test :refer :all] 4 | [puppetlabs.puppetdb.integration.fixtures :as int] 5 | [puppetlabs.puppetdb.testutils :refer [with-caught-ex-info]] 6 | [puppetlabs.trapperkeeper.app :as tk-app])) 7 | 8 | (deftest ^:integration db-fallback 9 | (with-open [pg1 (int/setup-postgres) 10 | pg2 (int/setup-postgres) 11 | pdb1 (int/run-puppetdb pg1 {}) 12 | pdb2 (int/run-puppetdb pg2 {}) 13 | ps (int/run-puppet-server [pdb1 pdb2] {})] 14 | 15 | (testing "Agent run against pdb1" 16 | (int/run-puppet ps pdb1 "notify { 'initial': }") 17 | (is (= 1 (count (int/pql-query pdb1 "resources { title='initial' }")))) 18 | (is (= 0 (count (int/pql-query pdb2 "resources { title='initial' }"))))) 19 | 20 | (testing "Fallback to pdb2" 21 | (tk-app/stop (:app pdb1)) 22 | (int/run-puppet ps pdb2 "notify { 'fallback': }") 23 | (is (= 1 (count (int/pql-query pdb2 "resources { title='fallback' }"))))) 24 | 25 | (testing "Restore pdb1" 26 | (tk-app/start (:app pdb1)) 27 | (int/run-puppet ps pdb1 "notify { 'restored': }") 28 | (is (= 1 (count (int/pql-query pdb1 "resources { title='restored' }")))) 29 | (is (= 0 (count (int/pql-query pdb2 "resources { title='restored' }"))))))) 30 | 31 | (deftest ^:integration soft-write-fail 32 | (with-open [pg (int/setup-postgres) 33 | pdb (int/run-puppetdb pg {}) 34 | ps (int/run-puppet-server [pdb] {:terminus {:main {:soft_write_failure true}}})] 35 | (tk-app/stop (-> pdb int/server-info :app)) 36 | 37 | (testing "Agent run should fail for manifest which collects resources" 38 | (let [ex (with-caught-ex-info 39 | (int/run-puppet ps pdb "Notify <<| |>>")) 40 | data (ex-data ex)] 41 | (is (= ::int/bundle-exec-failure (:kind data))) 42 | (is (re-find #"Could not retrieve resources from the PuppetDB" 43 | (get-in data [:result :err]))))) 44 | 45 | (testing "Agent run should succeed for manifest which exports resources" 46 | (int/run-puppet ps pdb "@@notify { 'exported notify': }")))) 47 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/meta/version_test.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.meta.version-test 2 | (:require 3 | [clojure.test :refer :all] 4 | [puppetlabs.puppetdb.meta.version :as version] 5 | [puppetlabs.puppetdb.testutils.db :refer [with-test-db *db*]])) 6 | 7 | (deftest check-for-updates!-test 8 | (testing "check-for-updates! swallows exceptions" 9 | (testing "can't connect to server" 10 | (with-test-db 11 | (is (nil? (version/check-for-updates! "http://updates.foo.com" *db*))))) 12 | (testing "can't connect to database" 13 | (is (nil? (version/check-for-updates! "http://updates.puppetlabs.com" 14 | {:invalid :connection})))))) 15 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/query/regression_test.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.query.regression-test 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as str] 5 | [clojure.test :refer [deftest is testing]] 6 | [puppetlabs.puppetdb.cheshire :as json] 7 | [puppetlabs.puppetdb.testutils.db :refer [with-test-db]] 8 | [puppetlabs.puppetdb.testutils.http 9 | :refer [query-response with-http-app]] 10 | [puppetlabs.puppetdb.testutils.parse-yaml :refer [parse-yaml]])) 11 | 12 | 13 | (deftest collected-queries-still-working 14 | (with-test-db 15 | (with-http-app 16 | (doseq [file (->> "locust/load-test" 17 | io/as-file 18 | file-seq 19 | (filter #(str/ends-with? % ".yaml"))) 20 | request-data (parse-yaml (slurp file)) 21 | :let [{:keys [alias method path query]} request-data 22 | keyword-method (case method 23 | "GET" :get 24 | "POST" :post) 25 | relative-path (str/replace-first path #"^/pdb/query" "")]] 26 | (testing (str "testing " alias " in " file) 27 | (let [{:keys [status body]} 28 | (query-response keyword-method relative-path query)] 29 | ;; If body of response is not valid JSON, the test should fail 30 | (is (-> body slurp json/parse-string)) 31 | ;; If status of response is not 200, the test should fail 32 | (is (= 200 status)))))))) 33 | 34 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/test_import.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.test-import 2 | (:require [clojure.test :refer :all] 3 | [puppetlabs.puppetdb.import :refer [command-matcher]] 4 | [puppetlabs.puppetdb.scf.hash :as hash] 5 | [puppetlabs.puppetdb.time :refer [now]])) 6 | 7 | (defn cmd-path-with-hash [entity producer-ts-hash certname] 8 | (format "puppetdb-bak/%s/%s-%s.json" entity certname producer-ts-hash)) 9 | 10 | (def producer-ts-hash (hash/generic-identity-hash (now))) 11 | 12 | (deftest extract-command-with-hash 13 | (doseq [entity ["catalogs" "reports"]] 14 | (are [certname] (= (-> entity 15 | (cmd-path-with-hash producer-ts-hash certname) 16 | command-matcher) 17 | [entity certname]) 18 | "foo.com" 19 | "foo" 20 | "some-really-long-name-with-dashes" 21 | "some-name-with-double-json.json"))) 22 | 23 | (defn facts-path [certname] 24 | (format "puppetdb-bak/facts/%s.json" certname)) 25 | 26 | (deftest test-extract-facts-certname 27 | (are [certname] (= (command-matcher (facts-path certname)) 28 | ["facts" certname]) 29 | "foo.com" 30 | "foo" 31 | "some-really-long-name-with-dashes" 32 | "some-name-with-double-json.json")) 33 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/test_protocols.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.test-protocols 2 | (:require [clojure.test :refer :all])) 3 | 4 | ;; A protocol to be reified alongside IFn; after the function has been 5 | ;; called once, called? should return true. 6 | (defprotocol IMockFn 7 | (called? [this])) 8 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/testutils/dashboard.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.testutils.dashboard) 2 | 3 | (defn dashboard-base-url->str 4 | "Similar to puppetlabs.puppetdb.utils/base-url->str but doesn't 5 | include a version as the dashboard page does not include a version" 6 | [{:keys [protocol host port prefix] :as _base-url}] 7 | (-> (java.net.URL. protocol host port prefix) 8 | .toURI .toASCIIString)) 9 | 10 | (defn dashboard-page? [{:keys [body] :as _req}] 11 | (.contains body "PuppetDB: Dashboard")) 12 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/testutils/facts.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.testutils.facts 2 | (:require 3 | [puppetlabs.puppetdb.utils :as utils])) 4 | 5 | (def base-facts 6 | "A minimal set of facts useful for testing" 7 | {"hardwaremodel" "x86_64" 8 | "memorysize" "16.00 GB" 9 | "memorytotal" "16.00 GB" 10 | "puppetversion" "3.4.2" 11 | "ipaddress_lo0" "127.0.0.1" 12 | "id" "foo" 13 | "operatingsystem" "Debian"}) 14 | 15 | (def base-package-inventory 16 | [["ntp" "4.2.8" "apt"] 17 | ["puppet-agent" "6.6.0" "apt"] 18 | ["nokogiri" "4.5.6" "gem"]]) 19 | 20 | (defn create-host-facts 21 | "Create a map for `node` suitable for spitting to a tarball 22 | used by import/export/anonymize" 23 | [node additional-facts] 24 | {"facts" 25 | {node 26 | {"certname" node 27 | "environment" "DEV" 28 | "values" (merge base-facts additional-facts)}}}) 29 | 30 | (defn munge-facts 31 | [facts] 32 | (->> facts 33 | utils/vector-maybe 34 | (map #(dissoc % :producer_timestamp :hash)))) 35 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/testutils/log.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.testutils.log 2 | (:import 3 | [ch.qos.logback.classic Level])) 4 | 5 | ;;The below functions are useful with 6 | ;;puppetlabs.trapperkeeper.testutils.logging/with-log-suppressed-unless-notable 7 | 8 | (defn notable-pdb-event? [event] 9 | (.isGreaterOrEqual (.getLevel event) Level/ERROR)) 10 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/testutils/mem.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.testutils.mem 2 | (:require [clojure.java.shell :as shell]) 3 | (:import [java.lang.management ManagementFactory] 4 | [java.nio.file Files NoSuchFileException])) 5 | 6 | (def getpid 7 | "Returns the integer PID of the current process." 8 | (let [pid (atom nil)] 9 | (fn [] 10 | (if-let [p @pid] 11 | p 12 | (reset! pid (->> (ManagementFactory/getRuntimeMXBean) 13 | .getName 14 | (re-find #"[0-9]+") 15 | Integer/parseInt)))))) 16 | 17 | (defn dump-heap 18 | "Dumps the current heap to filename via jmap." 19 | [filename] 20 | (try 21 | ;; Because jmap quietly does nothing if the file exists. 22 | (-> filename java.io.File. .toPath Files/delete) 23 | (catch NoSuchFileException _ 24 | true)) 25 | (assert (zero? 26 | (:exit (shell/sh "jmap" 27 | (str "-dump:live,format=b,file=" filename) 28 | (str (getpid))))))) 29 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/testutils/nio.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.testutils.nio 2 | (:require 3 | [me.raynes.fs :refer [delete-dir]] 4 | [puppetlabs.puppetdb.lint :refer [ignore-value]]) 5 | (:import 6 | [java.nio.file Path Files] 7 | [java.nio.file.attribute FileAttribute])) 8 | 9 | (defn create-temp-dir 10 | ([^String prefix] 11 | (Files/createTempDirectory prefix (into-array FileAttribute []))) 12 | ([^Path path ^String prefix] 13 | (ignore-value (Files/createDirectories path (into-array FileAttribute []))) 14 | (Files/createTempDirectory path prefix (into-array FileAttribute [])))) 15 | 16 | (defn resolve-path [^Path path ^String suffix] 17 | (.resolve path suffix)) 18 | 19 | (defn call-with-temp-dir-path 20 | "Calls (f temp-dir-path) after creating the temporary directory 21 | inside the parent path, and then deletes the directory if f doesn't 22 | throw an Exception. Prepends the prefix, if not nil, to the 23 | temporary directory's name." 24 | [parent prefix f] 25 | (let [tempdir (Files/createTempDirectory parent prefix 26 | (make-array FileAttribute 0)) 27 | tempdirstr (str (.toAbsolutePath tempdir)) 28 | result (try 29 | (f (.toAbsolutePath tempdir)) 30 | (catch Exception ex 31 | (binding [*out* *err*] 32 | (println "Error: leaving temp dir" tempdirstr)) 33 | (throw ex)))] 34 | (delete-dir tempdirstr) 35 | result)) 36 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/testutils/parse_yaml.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.testutils.parse-yaml 2 | (:import (java.util List Map Set) 3 | (org.yaml.snakeyaml Yaml))) 4 | 5 | (defprotocol JavaMap->ClojureMap 6 | (java->clj [o])) 7 | 8 | (extend-protocol JavaMap->ClojureMap 9 | Map 10 | (java->clj [o] (let [entries (.entrySet o)] 11 | (reduce (fn [m [^String k v]] 12 | (assoc m (keyword k) (java->clj v))) 13 | {} entries))) 14 | 15 | List 16 | (java->clj [o] (vec (map java->clj o))) 17 | 18 | Set 19 | (java->clj [o] (set (map java->clj o))) 20 | 21 | Object 22 | (java->clj [o] o) 23 | 24 | nil 25 | (java->clj [_] nil)) 26 | 27 | (defn parse-yaml 28 | [yaml-string] 29 | ;; default in snakeyaml 2.0 is to not allow 30 | ;; global tags, which is the source of exploits. 31 | (let [yaml (new Yaml) 32 | data (.load yaml ^String yaml-string)] 33 | (java->clj data))) -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/testutils/tar.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.testutils.tar 2 | (:require [puppetlabs.puppetdb.archive :as archive] 3 | [clojure.string :as str] 4 | [me.raynes.fs :as fs] 5 | [puppetlabs.puppetdb.utils :as utils] 6 | [puppetlabs.puppetdb.time :refer [now]])) 7 | 8 | (defn path 9 | "Creates a platform independent relative path built 10 | from `path-segments`" 11 | [& path-segments] 12 | (str/join java.io.File/separator path-segments)) 13 | 14 | (defn assoc-metadata 15 | "Creates an export/import metadata map with the current 16 | time." 17 | [tar-map] 18 | (assoc tar-map 19 | (path "puppetdb-bak" "export-metadata.json") 20 | {"timestamp" (now) 21 | "command_versions" {"replace_facts" 4 22 | "replace_catalog" 6 23 | "store_report" 5}})) 24 | 25 | (defn tar-entry->map-path 26 | [tar-entry] 27 | (-> (.getName tar-entry) fs/split rest vec)) 28 | 29 | (defn tar->map 30 | "Convert elements in an import/export tarball to a hashmap. 31 | Nested directories convert to nested maps with the files 32 | converted from JSON to clojure data structures" 33 | [tar-file] 34 | (with-open [tar-reader (archive/tarball-reader tar-file)] 35 | (reduce (fn [acc tar-entry] 36 | (assoc-in acc 37 | (tar-entry->map-path tar-entry) 38 | (utils/read-json-content tar-reader))) 39 | {} (archive/all-entries tar-reader)))) 40 | -------------------------------------------------------------------------------- /test/puppetlabs/puppetdb/utils/metrics_test.clj: -------------------------------------------------------------------------------- 1 | (ns puppetlabs.puppetdb.utils.metrics-test 2 | (:require [puppetlabs.puppetdb.utils.metrics :as mutils] 3 | [clojure.test :refer :all] 4 | [metrics.timers :refer [timer]])) 5 | 6 | (deftest test-multitime-macro 7 | (testing "should update all supplied timers" 8 | (let [timers (mapv timer ["t1" "t2" "t3"])] 9 | (doseq [t timers] 10 | (is (zero? (mutils/number-recorded t)))) 11 | (is (= 6 (mutils/multitime! timers (+ 1 2 3)))) 12 | (doseq [t timers] 13 | (is (= 1 (mutils/number-recorded t))))))) 14 | -------------------------------------------------------------------------------- /util/bin/pdb: -------------------------------------------------------------------------------- 1 | ../pdb/pdb -------------------------------------------------------------------------------- /util/pdb/README.md: -------------------------------------------------------------------------------- 1 | ## Next generation developer utilities for PDB 2 | 3 | A python CLI utility for 4 | 5 | * load simulation (currently in a hacky state, only supporting facts) 6 | * querying (no streaming, possibly broken) 7 | 8 | ### Setup 9 | 10 | * Install virtualenv and python 3 11 | apt-get install virtualenv 12 | 13 | * Set up virtualenv 14 | virtualenv -p python3 venv 15 | source venv/bin/activate 16 | pip install -r requirements.txt 17 | 18 | * Run the tool 19 | ./pdb simulate 100000 30 20 | -------------------------------------------------------------------------------- /util/pdb/pdb: -------------------------------------------------------------------------------- 1 | """": # -*-python-*- 2 | command -v python3 > /dev/null && exec python3 "$0" "$@" 3 | command -v python2 > /dev/null && exec python2 "$0" "$@" 4 | echo "error: unable to find python3 or python2" 1>&2; exit 2 5 | """ 6 | 7 | import sys 8 | from puppetdb import PuppetDB 9 | 10 | if __name__ == '__main__': 11 | pdb = PuppetDB() 12 | subcommand = sys.argv[1] 13 | if subcommand == 'simulate': 14 | nhosts, interval = sys.argv[2:] 15 | pdb.simulate(int(nhosts), int(interval)) 16 | if subcommand == 'query': 17 | pdb.query(sys.argv[2]) 18 | -------------------------------------------------------------------------------- /util/pdb/requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | ijson 3 | grequests 4 | -------------------------------------------------------------------------------- /util/pdb/samples: -------------------------------------------------------------------------------- 1 | ../../resources/puppetlabs/puppetdb/benchmark/samples --------------------------------------------------------------------------------