|
27 | 27 | 1. [Contributors](#contributors) |
28 | 28 | 1. [See Also](#see-also) |
29 | 29 | 1. [Upload facts to PuppetDB](#upload-facts-to-puppetdb) |
| 30 | + 1. [Modern fact submission](#modern-fact-submission) |
30 | 31 |
|
31 | 32 |
|
32 | 33 | ## Overview |
@@ -336,8 +337,134 @@ version 3 to Masters running version 5. It uses the [`/puppet/v3/facts/` API](ht |
336 | 337 | which is available in version 3 and >= 5 of Puppet. This API was removed in Puppet 4 but |
337 | 338 | added again in 5. |
338 | 339 |
|
339 | | -### Further documentation |
| 340 | +### Modern fact submission |
| 341 | + |
| 342 | +Nowadays it's possible to use `puppet facts upload --server $new_server` to |
| 343 | +submit facts to a new server. This however requires that the new puppetserver |
| 344 | +and the old one share one certificate authority. You can easily run this once |
| 345 | +via bolt to get all facts to a new puppetserver. |
| 346 | + |
| 347 | +### complex fact submission |
| 348 | + |
| 349 | +To every problem an overengineered solution exists! Let's assume this: |
| 350 | +You have an existing Puppet environment. You setup a new Puppetserver, |
| 351 | +with a newer Puppet version and a new CA. You have a third box with |
| 352 | +catalog_diff, that has certificates to access the old and new Puppetserver. Now |
| 353 | +for catalog_diff to work, we need to get the facts from the old environment to |
| 354 | +the new one. There are three little scripts that you can use to: |
| 355 | + |
| 356 | +* download facts from old PuppetDB |
| 357 | +* Convert the format |
| 358 | +* Submit them to the new Puppetserver |
| 359 | + |
| 360 | +It's best to run them on the catalog_diff box, since it already has certificates |
| 361 | +that allow it to access all required APIs: |
| 362 | + |
| 363 | + |
| 364 | +```bash |
| 365 | +#!/bin/bash |
| 366 | + |
| 367 | + |
| 368 | +#differ_certs/ |
| 369 | +#├── catalog-diff_dev |
| 370 | +#│ ├── ca |
| 371 | +#│ │ └── ca.pem |
| 372 | +#│ ├── cert |
| 373 | +#│ │ └── catalog-diff.pem |
| 374 | +#│ └── private |
| 375 | +#│ └── catalog-diff.pem |
| 376 | +#├── catalog-diff_prod |
| 377 | +#│ ├── ca |
| 378 | +#│ │ └── ca.pem |
| 379 | +#│ ├── cert |
| 380 | +#│ │ └── catalog-diff.pem |
| 381 | +#│ └── private |
| 382 | +#│ └── catalog-diff.pem |
| 383 | + |
| 384 | + |
| 385 | +certs_dir="${HOME}/differ_certs" |
| 386 | +certs_dev="${certs_dir}/catalog-diff_dev" |
| 387 | +certs_prod="${certs_dir}/catalog-diff_prod" |
| 388 | +cert='catalog-diff.pem' |
| 389 | +puppetdb_dev=puppet-dev.local |
| 390 | +puppetdb_prod=puppet-prod.local |
| 391 | +clientcert_dev="${certs_dev}/cert/${cert}" |
| 392 | +clientcert_prod="${certs_prod}/cert/${cert}" |
| 393 | +clientkey_dev="${certs_dev}/private/${cert}" |
| 394 | +clientkey_prod="${certs_prod}/private/${cert}" |
| 395 | +cacert_dev="${certs_dev}/ca/ca.pem" |
| 396 | +cacert_prod="${certs_prod}/ca/ca.pem" |
| 397 | + |
| 398 | +function prod_facts() { |
| 399 | + curl --request GET \ |
| 400 | + --url "https://${puppetdb_prod}:8081/pdb/query/v4/factsets" \ |
| 401 | + --cert "${clientcert_prod}" \ |
| 402 | + --cacert "${cacert_prod}" \ |
| 403 | + --key "${clientkey_prod}" \ |
| 404 | + --silent \ |
| 405 | + | jq -cr '.[] | .certname, .' | awk 'NR%2{f="factsets/"$0".json";next} {print >f;close(f)}' |
| 406 | +} |
| 407 | + |
| 408 | +function dev_facts() { |
| 409 | + curl --request GET \ |
| 410 | + --url "https://${puppetdb_dev}:8081/pdb/query/v4/factsets" \ |
| 411 | + --cert "${clientcert_dev}" \ |
| 412 | + --cacert "${cacert_dev}" \ |
| 413 | + --key "${clientkey_dev}" \ |
| 414 | + --silent \ |
| 415 | + | jq -cr '.[] | .certname, .' | awk 'NR%2{f="factsets/"$0".json";next} {print >f;close(f)}' |
| 416 | +} |
| 417 | + |
| 418 | +function facts() { |
| 419 | + dev_facts |
| 420 | + prod_facts |
| 421 | +} |
| 422 | +facts |
| 423 | +``` |
340 | 424 |
|
| 425 | +```ruby |
| 426 | +#!/opt/puppetlabs/puppet/bin/ruby |
| 427 | + |
| 428 | +require 'json' |
| 429 | +require 'date' |
| 430 | + |
| 431 | +Dir[Dir.home + "/factsets/*.json"].each do |file| |
| 432 | + filename = File.basename(file) |
| 433 | + puts "processing #{filename}" |
| 434 | + facts = JSON.parse(File.read(file)) |
| 435 | + real_facts = { } |
| 436 | + real_facts['values'] = facts['facts']['data'].map{|facthash| {facthash['name'] => facthash['value']}}.reduce({}, :merge) |
| 437 | + real_facts['name'] = facts['certname'] |
| 438 | + real_facts['timestamp'] = facts['timestamp'] |
| 439 | + # expiration is usually timestamp + runintervall. We use 30min here |
| 440 | + real_facts['expiration'] = DateTime.parse(facts['timestamp']) + Rational(30 * 60, 86400) |
| 441 | + File.open(Dir.home + "/facts/#{filename}","w") do |f| f.write("#{JSON.pretty_generate(real_facts)}\n") end |
| 442 | +end |
| 443 | +``` |
| 444 | + |
| 445 | +```bash |
| 446 | +#!/bin/bash |
| 447 | + |
| 448 | +hostcert="$(puppet config print hostcert)" |
| 449 | +hostprivkey="$(puppet config print hostprivkey)" |
| 450 | +localcacert="$(puppet config print localcacert)" |
| 451 | +server="$(puppet config print server)" |
| 452 | +for file in facts/*json; do |
| 453 | + filename="$(basename $file)" |
| 454 | + certname="$(basename $filename '.json')" |
| 455 | + environment="$(jq --raw-output .environment factsets/${filename})" |
| 456 | + curl --include \ |
| 457 | + --request PUT \ |
| 458 | + --cert "${hostcert}" \ |
| 459 | + --key "${hostprivkey}" \ |
| 460 | + --cacert "${localcacert}" \ |
| 461 | + --data @"${file}" \ |
| 462 | + --url "https://${server}:8140/puppet/v3/facts/${certname}?environment=${environment}" \ |
| 463 | + --header 'Content-Type: application/json' |
| 464 | +done |
| 465 | +``` |
| 466 | + |
| 467 | +### Further documentation |
341 | 468 |
|
342 | 469 | * Raphaël Pinson wrote a [blog series on dev.to](https://dev.to/camptocamp-ops/diffing-puppet-environments-1fno) about using puppet-catalog-diff and GitLab integration |
343 | 470 | * Raphaël Pinson also made two talks about it: |
|
0 commit comments