├── util
├── bin
│ └── pdb
└── pdb
│ ├── requirements.txt
│ ├── samples
│ ├── README.md
│ └── pdb
├── ext
├── .gitignore
├── test-conf
│ ├── pgver-default
│ ├── puppet-ref-default
│ └── puppetserver-ref-default
├── build_defaults.yaml
├── bin
│ ├── sha256sum
│ ├── run-rspec-tests
│ ├── clj-1.11
│ ├── jdk-from-spec
│ ├── symlink-relative-to
│ ├── spec-includes
│ ├── prefixed-ref-from-spec
│ ├── flavor-from-spec
│ ├── host-info
│ ├── check-spec-env
│ ├── contributors-in-git-log
│ ├── run-external-tests
│ ├── pdbbox-env
│ ├── require-pgbox
│ ├── prep-debianish
│ └── require-leiningen
├── project_data.yaml
├── jenkins
│ ├── terminus-rspec.sh
│ ├── lein-test.sh
│ ├── beaker-tests-source.sh
│ └── beaker-tests.sh
└── test
│ └── top-level-cli
├── resources
├── ext
│ ├── docs
│ ├── config
│ │ ├── bootstrap.cfg
│ │ ├── conf.d
│ │ │ ├── repl.ini
│ │ │ ├── database.ini
│ │ │ ├── config.ini
│ │ │ ├── jetty.ini
│ │ │ └── auth.conf
│ │ └── request-logging.xml
│ └── cli
│ │ ├── anonymize
│ │ └── upgrade
├── puppetlabs
│ └── puppetdb
│ │ ├── benchmark
│ │ └── config.ini
│ │ ├── generate
│ │ └── realistic
│ │ │ ├── README.md
│ │ │ └── metadata.txt
│ │ └── bootstrap.cfg
└── logback.xml
├── Makefile
├── test-resources
├── puppetserver
│ ├── ssl
│ │ ├── ca
│ │ │ ├── serial
│ │ │ ├── inventory.txt
│ │ │ ├── ca_pub.pem
│ │ │ ├── ca_crl.pem
│ │ │ └── signed
│ │ │ │ └── localhost.pem
│ │ ├── public_keys
│ │ │ └── localhost.pem
│ │ ├── crl.pem
│ │ └── certs
│ │ │ └── localhost.pem
│ ├── rich_data_environment.conf
│ ├── rich_data_puppet.conf
│ ├── puppet.conf
│ ├── request-logging-dev.xml
│ ├── logback-dev.xml
│ ├── bootstrap-7.x.cfg
│ └── bootstrap.cfg
├── binary-template.erb
├── create-test-db.sh
├── logback-test.xml
├── integration-bootstrap.cfg
├── puppetlabs
│ └── puppetdb
│ │ ├── ssl
│ │ ├── public_keys
│ │ │ └── localhost.pem
│ │ ├── private_keys
│ │ │ └── keyonly.pem
│ │ └── certs
│ │ │ ├── ca.pem
│ │ │ └── localhost.pem
│ │ └── cli
│ │ └── export
│ │ └── tiny-catalog.json
├── integration-puppetdb.conf
├── ca.pem
└── localhost.pem
├── CODEOWNERS
├── documentation
├── release_notes.markdown
├── images
│ ├── pdb_erd.png
│ ├── perf-dash-large.png
│ └── perf-dash-small.png
├── README.md
├── api
│ ├── wire_format
│ │ ├── facts_format_v4.markdown
│ │ ├── facts_format_v5.markdown
│ │ └── deactivate_node_format_v3.markdown
│ ├── meta
│ │ └── v1
│ │ │ ├── server-time.markdown
│ │ │ └── version.markdown
│ ├── query
│ │ └── v4
│ │ │ └── fact-names.markdown
│ └── admin
│ │ └── v1
│ │ └── archive.markdown
└── using.markdown
├── .gitattributes
├── puppet
├── spec
│ ├── spec.opts
│ ├── README.markdown
│ ├── unit
│ │ ├── indirector
│ │ │ ├── facts
│ │ │ │ └── puppetdb_apply_spec.rb
│ │ │ └── node
│ │ │ │ └── puppetdb_spec.rb
│ │ ├── face
│ │ │ └── node
│ │ │ │ ├── deactivate_spec.rb
│ │ │ │ └── status_spec.rb
│ │ └── util
│ │ │ └── puppetdb_spec.rb
│ └── spec_helper.rb
└── lib
│ └── puppet
│ ├── functions
│ └── puppetdb_query.rb
│ ├── util
│ └── puppetdb
│ │ ├── command_names.rb
│ │ └── atom.rb
│ ├── indirector
│ ├── node
│ │ └── puppetdb.rb
│ └── facts
│ │ └── puppetdb_apply.rb
│ └── face
│ └── node
│ └── deactivate.rb
├── .dockerignore
├── .dir-locals.el
├── contrib
├── gem
│ ├── Gemfile
│ ├── README.md
│ └── puppetdb-terminus.gemspec
└── README.md
├── dev-resources
├── time-shift-export
│ └── input-archive
│ │ ├── facts
│ │ └── facts.json
│ │ ├── catalogs
│ │ └── catalog.json
│ │ ├── export-metadata.json
│ │ └── reports
│ │ └── report.json
└── suppression.xml
├── dev-docs
├── README.md
└── run-pdb-on-macos.md
├── test
└── puppetlabs
│ └── puppetdb
│ ├── test_protocols.clj
│ ├── testutils
│ ├── log.clj
│ ├── dashboard.clj
│ ├── parse_yaml.clj
│ ├── facts.clj
│ ├── mem.clj
│ ├── nio.clj
│ └── tar.clj
│ ├── utils
│ └── metrics_test.clj
│ ├── meta
│ └── version_test.clj
│ ├── integration
│ ├── masterless.clj
│ ├── file_with_binary_template.clj
│ └── terminus_failover.clj
│ ├── http
│ ├── query_test.clj
│ └── sync_version_checking.clj
│ ├── cli
│ ├── util_test.clj
│ ├── pdb_dataset_test.clj
│ └── time_shift_export_test.clj
│ ├── test_import.clj
│ ├── generative
│ └── overrideable_generators_test.clj
│ ├── query
│ └── regression_test.clj
│ ├── core_test.clj
│ ├── dashboard_test.clj
│ └── archive_test.clj
├── acceptance
├── options
│ ├── common.rb
│ └── postgres.rb
├── setup
│ ├── post_suite
│ │ ├── 10_collect_artifacts.rb
│ │ └── 99_teardown.rb
│ ├── pre_suite
│ │ ├── 00_setup_test_env.rb
│ │ ├── 05_clear_firewalls.rb
│ │ ├── 30_generate_ssl_certs.rb
│ │ ├── 80_add_dev_repo.rb
│ │ ├── 50_install_modules.rb
│ │ ├── 70_install_released_puppetdb.rb
│ │ ├── 20_install_puppet.rb
│ │ ├── 75_clean_out_puppet5_repos.rb
│ │ └── 90_install_devel_puppetdb.rb
│ └── early
│ │ └── 00_remove_previous_config.rb
├── config
│ ├── vbox-debian7-64mda.cfg
│ ├── ec2-west-el7-64mda-el7-64a.cfg
│ └── vbox-debian7-64mda-2xdb.cfg
└── tests
│ ├── commands
│ ├── list-sub-commands.rb
│ ├── args-handling.rb
│ └── delete_reports.rb
│ ├── security
│ └── puppetdb-ssl-setup
│ │ ├── nonprod-environment.rb
│ │ ├── jetty-changes.rb
│ │ └── no-puppet-certs.rb
│ └── smoke.rb
├── src
└── puppetlabs
│ ├── puppetdb
│ ├── query
│ │ ├── common.clj
│ │ ├── edges.clj
│ │ ├── catalog_inputs.clj
│ │ ├── facts.clj
│ │ ├── resources.clj
│ │ └── fact_contents.clj
│ ├── lint.clj
│ ├── constants.clj
│ ├── package_util.clj
│ ├── nio.clj
│ ├── cli
│ │ ├── tk_util.clj
│ │ ├── version.clj
│ │ └── util.clj
│ ├── mq.clj
│ ├── honeysql.clj
│ ├── metrics
│ │ └── core.clj
│ ├── jdbc
│ │ └── internal.clj
│ ├── command
│ │ └── constants.clj
│ ├── meta
│ │ └── version.clj
│ ├── factsets.clj
│ ├── nodes.clj
│ └── core.clj
│ └── puppetdb.clj
├── .github
└── workflows
│ ├── docs_test.yml
│ ├── jira.yml
│ ├── docs_publish.yml
│ └── mend.yaml
├── locust
├── load-test
│ ├── example.yaml
│ └── cd4pe.yaml
└── run-load-test
├── locales
└── eo.po
├── NOTICE.txt
├── .mailmap
├── README.md
├── config.sample.ini
├── config
└── image_templates
│ └── ec2.yaml
├── .gitignore
└── .clj-kondo
└── config.edn
/util/bin/pdb:
--------------------------------------------------------------------------------
1 | ../pdb/pdb
--------------------------------------------------------------------------------
/ext/.gitignore:
--------------------------------------------------------------------------------
1 | files/*
2 |
--------------------------------------------------------------------------------
/ext/test-conf/pgver-default:
--------------------------------------------------------------------------------
1 | 11
2 |
--------------------------------------------------------------------------------
/resources/ext/docs:
--------------------------------------------------------------------------------
1 | ../../documentation
--------------------------------------------------------------------------------
/ext/test-conf/puppet-ref-default:
--------------------------------------------------------------------------------
1 | main
2 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | include dev-resources/Makefile.i18n
2 |
--------------------------------------------------------------------------------
/ext/test-conf/puppetserver-ref-default:
--------------------------------------------------------------------------------
1 | main
2 |
--------------------------------------------------------------------------------
/test-resources/puppetserver/ssl/ca/serial:
--------------------------------------------------------------------------------
1 | 002
2 |
--------------------------------------------------------------------------------
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @puppetlabs/dumpling @puppetlabs/skeletor
2 |
--------------------------------------------------------------------------------
/documentation/release_notes.markdown:
--------------------------------------------------------------------------------
1 | release_notes_8.markdown
--------------------------------------------------------------------------------
/util/pdb/requirements.txt:
--------------------------------------------------------------------------------
1 | requests
2 | ijson
3 | grequests
4 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | docker/** text eol=lf
2 | resources/** text eol=lf
3 |
--------------------------------------------------------------------------------
/resources/ext/config/bootstrap.cfg:
--------------------------------------------------------------------------------
1 | ../../puppetlabs/puppetdb/bootstrap.cfg
--------------------------------------------------------------------------------
/util/pdb/samples:
--------------------------------------------------------------------------------
1 | ../../resources/puppetlabs/puppetdb/benchmark/samples
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/puppet/spec/spec.opts:
--------------------------------------------------------------------------------
1 | --format
2 | s
3 | --colour
4 | --loadby
5 | mtime
6 | --backtrace
7 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | *
2 | !.git
3 | !project.clj
4 | !src
5 | !resources
6 | !documentation
7 | !docker
8 | !test
9 |
--------------------------------------------------------------------------------
/.dir-locals.el:
--------------------------------------------------------------------------------
1 | ((clojure-mode
2 | (clojure-docstring-fill-column . 79)
3 | (eval . (put-clojure-indent 'try! 0))))
4 |
--------------------------------------------------------------------------------
/documentation/images/pdb_erd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puppetlabs/puppetdb/HEAD/documentation/images/pdb_erd.png
--------------------------------------------------------------------------------
/ext/build_defaults.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | project: 'puppetdb'
3 | repo_name: 'puppet8'
4 | nonfinal_repo_name: 'puppet8-nightly'
5 |
--------------------------------------------------------------------------------
/test-resources/binary-template.erb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puppetlabs/puppetdb/HEAD/test-resources/binary-template.erb
--------------------------------------------------------------------------------
/test-resources/puppetserver/ssl/ca/inventory.txt:
--------------------------------------------------------------------------------
1 | 0x0001 2022-02-08T22:49:12UTC 2037-02-05T22:49:14UTC /CN=localhost
2 |
--------------------------------------------------------------------------------
/contrib/gem/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | # Specify your gem's dependencies in puppetdb-terminus.gemspec
4 | gemspec
5 |
--------------------------------------------------------------------------------
/documentation/images/perf-dash-large.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puppetlabs/puppetdb/HEAD/documentation/images/perf-dash-large.png
--------------------------------------------------------------------------------
/documentation/images/perf-dash-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puppetlabs/puppetdb/HEAD/documentation/images/perf-dash-small.png
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/catalogs/catalog.json:
--------------------------------------------------------------------------------
1 | {
2 | "certname" : "host-8",
3 | "producer_timestamp" : "2021-05-13T11:10:00.000Z"
4 | }
5 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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.
--------------------------------------------------------------------------------
/.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
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/dev-resources/suppression.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 | ^pkg:maven/org\.clojure/core\.cache@.*$
11 | CVE-2020-36448
12 |
13 |
14 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PuppetDB [](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/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 |
--------------------------------------------------------------------------------
/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)))
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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-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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/.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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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-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/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-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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------