-
Notifications
You must be signed in to change notification settings - Fork 106
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(PDK-1612) Add PDK::Context and context detection
Previously the PDK assumed it was always within a Puppet Module, but the PDK can be used in far more different contexts. This commit implements the PDK Context RFC [1], in preparation for other parts of the PDK to consume it, for example PDK validators: * Adds the base Context and three concrete contexts: None, Module and ControlRepo * Adds a memoized context object to PDK (PDK.context), for consumption by other parts of the PDK * Updates the module pdk compatibility methods to accept a module path instead of assume the PDK is always in a module. This is needed for the Module context to check if an arbitrary module is PDK compatible * Adds two test fixtures (a Puppet module and a control repo) for use by rspec for contex detection * Adds tests for context detection via PDK::Context.create [1] https://github.com/puppetlabs/pdk-planning/blob/master/RFCs/0007-add-pdk-context.md
- Loading branch information
1 parent
d3f2dc7
commit d075099
Showing
18 changed files
with
525 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
require 'pdk' | ||
|
||
module PDK | ||
module Context | ||
autoload :None, 'pdk/context/none' | ||
autoload :Module, 'pdk/context/module' | ||
autoload :ControlRepo, 'pdk/context/control_repo' | ||
|
||
# Automatically determines the PDK Context given a path. Create will continue up the directory tree until it | ||
# finds a valid context | ||
# @return [PDK::Context::AbstractContext] Returns a PDK::Context::None if the context could not be determined | ||
def self.create(context_path) | ||
return PDK::Context::None.new(context_path) unless PDK::Util::Filesystem.directory?(context_path) | ||
|
||
previous = nil | ||
current = PDK::Util::Filesystem.expand_path(context_path) | ||
until !PDK::Util::Filesystem.directory?(current) || current == previous | ||
# Control Repo detection | ||
return PDK::Context::ControlRepo.new(current, context_path) if PDK::ControlRepo.control_repo_root?(current) | ||
|
||
# Puppet Module detection | ||
# Note - The metadata.json file check should really be in PDK::Util.in_module_root? | ||
metadata_file = File.join(current, 'metadata.json') | ||
if PDK::Util::Filesystem.file?(metadata_file) || PDK::Util.in_module_root?(context_path) | ||
return PDK::Context::Module.new(current, context_path) | ||
end | ||
|
||
previous = current | ||
current = PDK::Util::Filesystem.expand_path('..', current) | ||
end | ||
PDK::Context::None.new(context_path) | ||
end | ||
|
||
# Abstract class which all PDK Contexts will subclass from. | ||
# @abstract | ||
class AbstractContext | ||
# The root of this context, for example the module root when inside a module. This is different from context_path | ||
# For example a Module context_path could be /path/to/module/manifests/ but the root_path will be /path/to/module as | ||
# that is the root of the Module context | ||
# @return [String, Nil] | ||
attr_reader :root_path | ||
|
||
# The path used to create this context, for example the current working directory. This is different from root_path | ||
# For example a Module context_path could be /path/to/module/manifests/ but the root_path will be /path/to/module as | ||
# that is the root of the Module context | ||
# @return [String] | ||
attr_reader :context_path | ||
|
||
# @param context_path [String] The path where this context was created from e.g. Dir.pwd | ||
def initialize(context_path) | ||
@context_path = context_path | ||
end | ||
|
||
# Whether the current context is compatible with the PDK e.g. in a Module context, whether it has the correct metadata.json content | ||
# @return [Boolean] Default is not compatible | ||
def pdk_compatible? | ||
false | ||
end | ||
|
||
# The friendly name to display for this context | ||
# @api private | ||
# @abstract | ||
def display_name; end | ||
|
||
# The context which this context is in. For example a Module Context (/controlrepo/site/profile) can be inside of a Control Repo context (/controlrepo) | ||
# The default is to search in the parent directory of this context | ||
# @return [PDK::Context::AbstractContext, Nil] Returns the parent context or nil if there is no parent. | ||
def parent_context | ||
# Default detection is just look for the context in the parent directory of this context | ||
@parent_context || PDK::Context.create(File.dirname(root_path)) | ||
end | ||
|
||
# Writes the current context information, and parent contexts, to the PDK Debug Logger. | ||
# This is mainly used by the PDK CLI when in debug mode to assist users to figure out why the PDK is misbehaving. | ||
# @api private | ||
def to_debug_log | ||
current = self | ||
depth = 1 | ||
loop do | ||
PDK.logger.debug("Detected #{current.display_name} at #{current.root_path.nil? ? current.context_path : current.root_path}") | ||
current = current.parent_context | ||
break if current.nil? | ||
depth += 1 | ||
# Circuit breaker in case there are circular references | ||
break if depth > 20 | ||
end | ||
nil | ||
end | ||
|
||
#:nocov: There's nothing to test here | ||
def to_s | ||
"#<#{self.class}:#{object_id}>#{context_path}" | ||
end | ||
#:nocov: | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
require 'pdk' | ||
|
||
module PDK | ||
module Context | ||
# Represents a context for a directory based Control Repository | ||
class ControlRepo < PDK::Context::AbstractContext | ||
# @param repo_root [String] The root path for the control repo. | ||
# @param context_path [String] The path where this context was created from e.g. Dir.pwd | ||
# @see PDK::Context::AbstractContext | ||
def initialize(repo_root, context_path) | ||
super(context_path) | ||
@root_path = repo_root | ||
end | ||
|
||
def pdk_compatible? | ||
# Currently there is nothing to determine compatibility with the PDK for a | ||
# Control Repo. For now assume everything is compatible | ||
true | ||
end | ||
|
||
#:nocov: | ||
# @see PDK::Context::AbstractContext.display_name | ||
def display_name | ||
_('a Control Repository context') | ||
end | ||
#:nocov: | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
require 'pdk' | ||
|
||
module PDK | ||
module Context | ||
# Represents a context for a Puppet Module | ||
class Module < PDK::Context::AbstractContext | ||
# @param module_root [String] The root path for the module. | ||
# @param context_path [String] The path where this context was created from e.g. Dir.pwd | ||
# @see PDK::Context::AbstractContext | ||
def initialize(module_root, context_path) | ||
super(context_path) | ||
@root_path = module_root | ||
end | ||
|
||
# @see PDK::Context::AbstractContext.pdk_compatible? | ||
def pdk_compatible? | ||
PDK::Util.module_pdk_compatible?(root_path) | ||
end | ||
|
||
#:nocov: | ||
# @see PDK::Context::AbstractContext.display_name | ||
def display_name | ||
_('a Puppet Module context') | ||
end | ||
#:nocov: | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
require 'pdk' | ||
|
||
module PDK | ||
module Context | ||
# Represents a context which the PDK does not know. For example | ||
# an empty directory | ||
class None < PDK::Context::AbstractContext | ||
#:nocov: | ||
# @see PDK::Context::AbstractContext.display_name | ||
def display_name | ||
_('an unknown context') | ||
end | ||
#:nocov: | ||
|
||
# @see PDK::Context::AbstractContext.parent_context | ||
def parent_context | ||
# An unknown context has no parent | ||
nil | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
forge 'https://forge.puppetlabs.com/' | ||
|
||
# Modules from the Puppet Forge | ||
mod 'puppetlabs-stdlib', '1.0.0' |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
modulepath = modules:site:$basemodulepath | ||
environment_timeout = 0 |
Empty file.
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"name": "testfixture-valid", | ||
"version": "0.1.0", | ||
"author": "testfixture", | ||
"summary": "Skeleton module test fixture", | ||
"license": "Apache-2.0", | ||
"source": "http://localhost", | ||
"dependencies": [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
require 'spec_helper' | ||
require 'pdk/context' | ||
|
||
describe PDK::Context::ControlRepo do | ||
subject(:context) { described_class.new(repo_root, nil) } | ||
|
||
let(:repo_root) { File.join(FIXTURES_DIR, 'control_repo') } | ||
|
||
it 'subclasses PDK::Context::AbstractContext' do | ||
expect(context).is_a?(PDK::Context::AbstractContext) | ||
end | ||
|
||
it 'remembers the repo root' do | ||
expect(context.root_path).to eq(repo_root) | ||
end | ||
|
||
it 'is PDK compatible' do | ||
expect(context.pdk_compatible?).to eq(true) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
require 'spec_helper' | ||
require 'pdk/context' | ||
|
||
describe PDK::Context::Module do | ||
subject(:context) { described_class.new(module_root, nil) } | ||
|
||
let(:module_root) { File.join(FIXTURES_DIR, 'puppet_module') } | ||
|
||
it 'subclasses PDK::Context::AbstractContext' do | ||
expect(context).is_a?(PDK::Context::AbstractContext) | ||
end | ||
|
||
it 'remembers the module root' do | ||
expect(context.root_path).to eq(module_root) | ||
end | ||
|
||
describe '.pdk_compatible?' do | ||
it 'calls PDK::Util to determine compatibility' do | ||
expect(PDK::Util).to receive(:module_pdk_compatible?).with(context.root_path).and_return(true) | ||
expect(context.pdk_compatible?).to eq(true) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
require 'spec_helper' | ||
require 'pdk/context' | ||
|
||
describe PDK::Context::None do | ||
subject(:context) { described_class.new(nil) } | ||
|
||
it 'subclasses PDK::Context::AbstractContext' do | ||
expect(context).is_a?(PDK::Context::AbstractContext) | ||
end | ||
|
||
it 'has no parent context' do | ||
expect(context.parent_context).to be_nil | ||
end | ||
end |
Oops, something went wrong.