{"id":22666536,"url":"https://github.com/waveclaw/puppet-facter_cacheable","last_synced_at":"2025-04-12T09:53:02.448Z","repository":{"id":57664184,"uuid":"58698773","full_name":"waveclaw/puppet-facter_cacheable","owner":"waveclaw","description":"Generic Fact caching for facter when used with Puppet","archived":false,"fork":false,"pushed_at":"2024-12-04T15:44:21.000Z","size":71,"stargazers_count":2,"open_issues_count":0,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-12T09:52:50.880Z","etag":null,"topics":["cache","facter","puppet"],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/waveclaw.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-05-13T04:16:16.000Z","updated_at":"2024-12-04T15:45:47.000Z","dependencies_parsed_at":"2024-10-18T22:43:57.201Z","dependency_job_id":null,"html_url":"https://github.com/waveclaw/puppet-facter_cacheable","commit_stats":{"total_commits":43,"total_committers":5,"mean_commits":8.6,"dds":"0.11627906976744184","last_synced_commit":"b92d83581c499ad23e1c502ef217af47a2d5b5d3"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waveclaw%2Fpuppet-facter_cacheable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waveclaw%2Fpuppet-facter_cacheable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waveclaw%2Fpuppet-facter_cacheable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waveclaw%2Fpuppet-facter_cacheable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/waveclaw","download_url":"https://codeload.github.com/waveclaw/puppet-facter_cacheable/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248550635,"owners_count":21122932,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cache","facter","puppet"],"created_at":"2024-12-09T14:15:37.755Z","updated_at":"2025-04-12T09:53:02.419Z","avatar_url":"https://github.com/waveclaw.png","language":"Ruby","readme":"# facter\\_cacheable\n\n| [![Build Status](https://travis-ci.org/waveclaw/puppet-facter_cacheable.svg?branch=master)](https://travis-ci.org/waveclaw/puppet-facter_cacheable) | [![Code Climate](https://codeclimate.com/github/waveclaw/puppet-facter_cacheable/badges/gpa.svg)](https://codeclimate.com/github/waveclaw/puppet-facter_cacheable) | [![Test Coverage](https://codeclimate.com/github/waveclaw/puppet-facter_cacheable/badges/coverage.svg)](https://codeclimate.com/github/waveclaw/puppet-facter_cacheable/coverage) |\n\n#### Table of Contents\n\n1. [Overview](#overview)\n2. [Module Description - What the module does and why it is useful](#module-description)\n3. [Setup - The basics of getting started with facter\\_cacheable](#setup)\n    * [What facter\\_cacheable affects](#what-facter\\_cacheable-affects)\n    * [Setup requirements](#setup-requirements)\n    * [Beginning with facter\\_cacheable](#beginning-with-facter\\_cacheable)\n4. [Usage - Configuration options and additional functionality](#usage)\n5. [Reference - An under-the-hood peek at what the module is doing and how](#reference)\n5. [Limitations - OS compatibility, etc.](#limitations)\n6. [Development - Guide for contributing to the module](#development)\n\n## Overview\n\nfacter\\_cacheable implements a Puppet feature for Facter that caches fact values for a given time.\n\nThe features are inspired by the [Puppet Blog on Facter](https://puppet.com/blog/facter-part-3-caching-and-ttl) from 2010.\n\n\u003e This does not always work correctly with Puppet Enterprise 2016.\n\u003e PE purges pugin-synced facts directories on each run.\n\u003e This removes fact files Puppet's agent thinks came from custom facts.\n\n## Module Description\n\nAs mentioned in many getting started with Puppet guides, including some by\nPuppet Labs, caching a fact can be useful.\nA well-maintained cache can:\n * reduce frequency of expensive calls\n * store values reachable outside of Puppet agent runs\n * explicitly control schedule of fact refreshing\n\n\nThere is limited planned support in Facter 2.0 and later for controlling some\ncaching of Puppet facts.  Personally this developer has never seen issues with it in the wild.\n\nNo, this is not yet-another-varnish module either.\n\n## Setup\n\n### What facter\\_cacheable affects\n\nDeploys a feature, facter\\_cacheable, which is usable for custom facts written\nby Puppet developers.\n\n### Setup Requirements\n\ncaching using this module requires at lest Ruby 2.3 and Puppet 4.7. Older releases cannot even run the test harness anymore.\n\nPluginSync must be enabled on at least one Puppet agent run to deploy the module.\n\n### Beginning with facter\\_cacheable\n\n## Usage\n\nThis module accepts no customization.  The `facter\\_cache()` call takes options for:\n * the value to cache\n * a time-to-live(ttl)\n * an optional location to store the cache in.\n\nIf the directories containing the cache files do not exist, the module will attempt to\ncreate them.\n\nTo cache a value use `cache`:\n```\nrequire 'facter/util/facter_cacheable'\nFacter::Util::FacterCacheable.cache(\n  :fact_name_symbol,\n  some_value,\n  optional_cache_file\n  )\n```\n\nTo return a cached value use `cached?`:\n```\nrequire 'facter/util/facter_cacheable'\nFacter::Util::FacterCacheable.cached?(\n  :fact_name_symbol,\n  ttl_in_seconds,\n  optional_cache_file)\n```\n\n*Complete Example*\n\n```\n#\n# my_module/lib/facter/my_custom_fact.rb\n#\nrequire 'facter'\nrequire 'puppet/util/facter_cachable'\n\nFacter.add(:my_custom_fact) do\n  confine do\n    Puppet.features.facter_cacheable?\n  end\n  setcode do\n    # 24 * 3600 = 1 day of seconds\n    cache = Facter::Util::FacterCacheable.cached?(:my_custom_fact, 24 * 3600)\n    if ! cache\n      my_value = some_expensive_operation()\n      # store the value for later\n      Facter::Util::FacterCacheable.cache(:my_custom_fact, my_value)\n      # return the expensive value\n      my_value\n    else\n      # return the cached value (this may need processing)\n      cache\n    end\n  end\nend\n```\n\nIt is not required but encouraged to keep the name of the cache and fact\nthe same. Although with all Ruby programming sanity is optional as it\nhaving documentation.\n\nYAML stored values may appear as arrays or string-indexed hashes depending on\nthe version of Puppet and Facter involved.  Unpacking those is left as an\nexercise for the reader.\n\n### Testing Code\n\nTo test code that uses Facter\\_cacheable you will have to resort to a little\nused [method for stubbing objects](https://github.com/rspec/rspec-mocks).\n\nIn your Facter fact guard against import of the module.  Import will fail if you\ndo not have it deployed to the Puppet environment on which the tests are running.\n\nNote: even the rSpec setup will not properly install this utility for testing.\n\n```ruby\nbegin\n    require 'facter/util/facter_cacheable'\n  rescue LoadError =\u003e e\n    Facter.debug(\"#{e.backtrace[0]}: #{$!}.\")\nend\n# regular fact like the complete example above\n```\n\nIn the rSpec Facter tests, normally some kind of function test on\n`Facter.value()`, setup a harness which can check for invocation of the cache\nfunctions.\n\n```ruby\ncontext 'test caching' do\n  let(:fake_class) { Class.new }\n  before :each do\n    allow(File).to receive(:exist?).and_call_original\n    allow(Puppet.features).to receive(:facter_cacheable?) { true }\n    Facter.clear\n  end\n  it 'should return and save a computed value with an empty cache' do\n    stub_const(\"Facter::Util::FacterCacheable\", fake_class)\n    expect(Facter::Util::FacterCacheable).to receive(:cached?).with(\n    :my_fact, 24 * 3600) { nil }\n    expect(Facter::Util::Resolution).to receive(:exec).with(\n    'some special comand') { mydata }\n    expect(Facter::Util::FacterCacheable).to receive(:cache).with(\n      :my_fact, mydata)\n    expect(Facter.value(:my_fact).to eq(mydata)\n  end\n  it 'should return a cached value with a full cache' do\n    stub_const(\"Facter::Util::FacterCacheable\", fake_class)\n    expect(Facter::Util::FacterCacheable).to receive(:cached?).with(\n    :my_fact, 24 * 3600) { mydata }\n    expect(mod).to_not receive(:my_fact)\n    expect(Facter.value(:my_fact)).to eq(mydata)\n  end\nend\n```\n\nThe key parts are the `:fake_class` and the `stub_const()` calls.  These setup\na kind of double that can be used by rSpec to hook into the Facter context.\n\n## Reference\n\n * [Facter Part 3: Caching and TTL](https://puppet.com/blog/facter-part-3-caching-and-ttl)\n * [Caching External Facts](https://projects.puppetlabs.com/projects/facter/wiki/CachingExternalFacts)\n * [Puppet Cookbook: Deploying Custom Facts](http://www.puppetcookbook.com/posts/deploying-custom-facts-in-modules.html)\n * [mcollective](https://github.com/breerly/puppet-modules/blob/master/mcollective/files/plugins/facts/facter/facter.rb) in puppet-modules\n * [Only two hard things in Computer Science](http://martinfowler.com/bliki/TwoHardThings.html)\n\n## Limitations\n\nSupports F/OSS Puppet 4.7.0+.  Tested on AIX, recent vintage Solaris, SuSE, RedHat and RedHat-derivatives.\n\nDoes not support Puppet Enterprise due to the cached value wipe on each run.\n\nDon't be surprised if is works elsewhere, too.  Or if it sets your house on fire.\n\nThe name of this module, facter\\_cacheable, was chosen to not conflict with other\nexisting implementations such as the `Facter::Util::Cacheable` support in early\nimplementations of `waveclaw/subscription_manager`.\n\n## Development\n\nPlease see CONTRIBUTING for advice on contributions.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwaveclaw%2Fpuppet-facter_cacheable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwaveclaw%2Fpuppet-facter_cacheable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwaveclaw%2Fpuppet-facter_cacheable/lists"}