Class: ChefDK::PolicyfileCompiler

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/chef-dk/policyfile_compiler.rb

Constant Summary collapse

DEFAULT_DEMAND_CONSTRAINT =
'>= 0.0.0'.freeze
SOURCE_TYPES_WITH_FIXED_VERSIONS =

Cookbooks from these sources lock that cookbook to exactly one version

[:git, :path].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializePolicyfileCompiler

Returns a new instance of PolicyfileCompiler.



50
51
52
53
# File 'lib/chef-dk/policyfile_compiler.rb', line 50

def initialize
  @dsl = Policyfile::DSL.new
  @artifact_server_cookbook_specs = {}
end

Instance Attribute Details

#dslObject (readonly)

Returns the value of attribute dsl.



48
49
50
# File 'lib/chef-dk/policyfile_compiler.rb', line 48

def dsl
  @dsl
end

Class Method Details

.evaluate(policyfile_string, policyfile_filename) ⇒ Object



37
38
39
40
41
# File 'lib/chef-dk/policyfile_compiler.rb', line 37

def self.evaluate(policyfile_string, policyfile_filename)
  compiler = new
  compiler.evaluate_policyfile(policyfile_string, policyfile_filename)
  compiler
end

Instance Method Details

#all_cookbook_specsObject



91
92
93
94
95
96
97
98
# File 'lib/chef-dk/policyfile_compiler.rb', line 91

def all_cookbook_specs
  # in the installation proces, we create "artifact_server_cookbook_specs"
  # for any cookbook that isn't sourced from a single-version source (e.g.,
  # path and git only support one version at a time), but we might have
  # specs for them to track additional version constraint demands. Merging
  # in this order ensures the artifact_server_cookbook_specs "win".
  policyfile_cookbook_specs.merge(@artifact_server_cookbook_specs)
end

#artifacts_graphObject



136
137
138
# File 'lib/chef-dk/policyfile_compiler.rb', line 136

def artifacts_graph
  remote_artifacts_graph.merge(local_artifacts_graph)
end

#build {|@dsl| ... } ⇒ Object

Yields:



181
182
183
184
# File 'lib/chef-dk/policyfile_compiler.rb', line 181

def build
  yield @dsl
  self
end

#cookbook_spec_for(cookbook_name) ⇒ Object



61
62
63
# File 'lib/chef-dk/policyfile_compiler.rb', line 61

def cookbook_spec_for(cookbook_name)
  policyfile_cookbook_specs[cookbook_name]
end

#cookbook_version_fixed?(cookbook_name) ⇒ Boolean

Returns:

  • (Boolean)


169
170
171
172
173
174
175
# File 'lib/chef-dk/policyfile_compiler.rb', line 169

def cookbook_version_fixed?(cookbook_name)
  if cookbook_spec = cookbook_spec_for(cookbook_name)
    cookbook_spec.version_fixed?
  else
    false
  end
end

#cookbooks_in_run_listObject



177
178
179
# File 'lib/chef-dk/policyfile_compiler.rb', line 177

def cookbooks_in_run_list
  run_list.map {|item_spec| Chef::RunList::RunListItem.new(item_spec).name }
end

#create_spec_for_cookbook(cookbook_name, version) ⇒ Object



85
86
87
88
89
# File 'lib/chef-dk/policyfile_compiler.rb', line 85

def create_spec_for_cookbook(cookbook_name, version)
  source_options = default_source.source_options_for(cookbook_name, version)
  spec = Policyfile::CookbookSpec.new(cookbook_name, "= #{version}", source_options, dsl)
  @artifact_server_cookbook_specs[cookbook_name] = spec
end

#error!Object



55
56
57
58
59
# File 'lib/chef-dk/policyfile_compiler.rb', line 55

def error!
  unless errors.empty?
    raise PolicyfileError, errors.join("\n")
  end
end

#evaluate_policyfile(policyfile_string, policyfile_filename) ⇒ Object



186
187
188
189
# File 'lib/chef-dk/policyfile_compiler.rb', line 186

def evaluate_policyfile(policyfile_string, policyfile_filename)
  @dsl.eval_policyfile(policyfile_string, policyfile_filename)
  self
end

#expanded_run_listObject



65
66
67
# File 'lib/chef-dk/policyfile_compiler.rb', line 65

def expanded_run_list
  run_list
end

#graphObject



110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/chef-dk/policyfile_compiler.rb', line 110

def graph
  @graph ||= Solve::Graph.new.tap do |g|
    artifacts_graph.each do |name, dependencies_by_version|
      dependencies_by_version.each do |version, dependencies|
        artifact = g.artifact(name, version)
        dependencies.each do |dep_name, constraint|
          artifact.dependency(dep_name, constraint)
        end
      end
    end
  end
end

#graph_demandsObject



123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/chef-dk/policyfile_compiler.rb', line 123

def graph_demands
  cookbooks_for_demands.map do |cookbook_name|
    spec = cookbook_spec_for(cookbook_name)
    if spec.nil?
      [ cookbook_name, DEFAULT_DEMAND_CONSTRAINT ]
    elsif spec.version_fixed?
      [ cookbook_name, "= #{spec.version}" ]
    else
      [ cookbook_name, spec.version_constraint.to_s ]
    end
  end
end

#graph_solutionObject

Compilation Methods



104
105
106
107
108
# File 'lib/chef-dk/policyfile_compiler.rb', line 104

def graph_solution
  return @solution if @solution
  cache_fixed_version_cookbooks
  @solution = Solve.it!(graph, graph_demands)
end

#installObject



73
74
75
76
77
78
79
80
81
82
83
# File 'lib/chef-dk/policyfile_compiler.rb', line 73

def install
  ensure_cache_dir_exists

  graph_solution.each do |cookbook_name, version|
    spec = cookbook_spec_for(cookbook_name)
    if spec.nil? or !spec.version_fixed?
      spec = create_spec_for_cookbook(cookbook_name, version)
      spec.ensure_cached
    end
  end
end

#local_artifacts_graphObject

Gives a dependency graph for cookbooks that are source from an alternate location. These cookbooks could have a different set of dependencies compared to an unmodified copy upstream. For example, the community site may have a cookbook “apache2” at version “1.10.4”, which the user has forked on github and modified the dependencies without changing the version number. To accomodate this, the local_artifacts_graph should be merged over the upstream’s artifacts graph.



147
148
149
150
151
152
153
154
# File 'lib/chef-dk/policyfile_compiler.rb', line 147

def local_artifacts_graph
  policyfile_cookbook_specs.inject({}) do |local_artifacts, (cookbook_name, cookbook_spec)|
    if cookbook_spec.version_fixed?
      local_artifacts[cookbook_name] = { cookbook_spec.version => cookbook_spec.dependencies }
    end
    local_artifacts
  end
end

#lockObject



69
70
71
# File 'lib/chef-dk/policyfile_compiler.rb', line 69

def lock
  @policyfile_lock ||= PolicyfileLock.build_from_compiler(self, cache_path: cache_path)
end

#remote_artifacts_graphObject



156
157
158
# File 'lib/chef-dk/policyfile_compiler.rb', line 156

def remote_artifacts_graph
  default_source.universe_graph
end

#version_constraint_for(cookbook_name) ⇒ Object



160
161
162
163
164
165
166
167
# File 'lib/chef-dk/policyfile_compiler.rb', line 160

def version_constraint_for(cookbook_name)
  if (cookbook_spec = cookbook_spec_for(cookbook_name)) and cookbook_spec.version_fixed?
    version = cookbook_spec.version
    "= #{version}"
  else
    DEFAULT_DEMAND_CONSTRAINT
  end
end