Class: Bolt::ModuleInstaller
- Inherits:
-
Object
- Object
- Bolt::ModuleInstaller
- Defined in:
- lib/bolt/module_installer.rb,
lib/bolt/module_installer/specs.rb,
lib/bolt/module_installer/resolver.rb,
lib/bolt/module_installer/installer.rb,
lib/bolt/module_installer/puppetfile.rb,
lib/bolt/module_installer/specs/id/base.rb,
lib/bolt/module_installer/specs/git_spec.rb,
lib/bolt/module_installer/specs/id/github.rb,
lib/bolt/module_installer/specs/id/gitlab.rb,
lib/bolt/module_installer/specs/forge_spec.rb,
lib/bolt/module_installer/puppetfile/module.rb,
lib/bolt/module_installer/specs/id/gitclone.rb,
lib/bolt/module_installer/puppetfile/git_module.rb,
lib/bolt/module_installer/puppetfile/forge_module.rb
Defined Under Namespace
Classes: Installer, Puppetfile, Resolver, Specs
Instance Method Summary collapse
-
#add(name, specs, puppetfile_path, moduledir, project_file, config) ⇒ Object
Adds a single module to the project.
-
#initialize(outputter, pal) ⇒ ModuleInstaller
constructor
A new instance of ModuleInstaller.
-
#install(specs, path, moduledir, config = {}, force: false, resolve: true) ⇒ Object
Installs a project’s module dependencies.
-
#install_puppetfile(path, moduledir, config = {}) ⇒ Object
Installs the Puppetfile and generates types.
-
#print_puppetfile_diff(old, new) ⇒ Object
Outputs a diff of an old Puppetfile and a new Puppetfile.
Constructor Details
#initialize(outputter, pal) ⇒ ModuleInstaller
Returns a new instance of ModuleInstaller.
12 13 14 15 16 |
# File 'lib/bolt/module_installer.rb', line 12 def initialize(outputter, pal) @outputter = outputter @pal = pal @logger = Bolt::Logger.logger(self) end |
Instance Method Details
#add(name, specs, puppetfile_path, moduledir, project_file, config) ⇒ Object
Adds a single module to the project.
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/bolt/module_installer.rb', line 20 def add(name, specs, puppetfile_path, moduledir, project_file, config) project_specs = Specs.new(specs, config) # Exit early if project config already includes a spec with this name. if project_specs.include?(name) @outputter.( "Project configuration file #{project_file} already includes specification "\ "with name #{name}. Nothing to do." ) return true end @outputter.("Adding module #{name} to project\n\n") # Generate the specs to resolve from. If a Puppetfile exists, parse it and # convert the modules to specs. Otherwise, use the project specs. resolve_specs = if puppetfile_path.exist? existing_puppetfile = Puppetfile.parse(puppetfile_path) existing_puppetfile.assert_satisfies(project_specs) Specs.from_puppetfile(existing_puppetfile) else project_specs end # Resolve module dependencies. Attempt to first resolve with resolve # specss. If that fails, fall back to resolving from project specs. # This prevents Bolt from modifying installed modules unless there is # a version conflict. @outputter.print_action_step("Resolving module dependencies, this might take a moment") @outputter.start_spin begin resolve_specs.add_specs('name' => name) puppetfile = Resolver.new.resolve(resolve_specs, config) rescue Bolt::Error project_specs.add_specs('name' => name) puppetfile = Resolver.new.resolve(project_specs, config) end @outputter.stop_spin # Display the diff between the existing Puppetfile and the new Puppetfile. print_puppetfile_diff(existing_puppetfile, puppetfile) # Add the module to the project configuration. @outputter.print_action_step("Updating project configuration file at #{project_file}") data = Bolt::Util.read_yaml_hash(project_file, 'project') data['modules'] ||= [] data['modules'] << name.tr('-', '/') begin File.write(project_file, data.to_yaml) rescue SystemCallError => e raise Bolt::FileError.new( "Unable to update project configuration file: #{e.}", project_file ) end # Write the Puppetfile. @outputter.print_action_step("Writing Puppetfile at #{puppetfile_path}") puppetfile.write(puppetfile_path, moduledir) # Install the modules. install_puppetfile(puppetfile_path, moduledir, config) end |
#install(specs, path, moduledir, config = {}, force: false, resolve: true) ⇒ Object
Installs a project’s module dependencies.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/bolt/module_installer.rb', line 150 def install(specs, path, moduledir, config = {}, force: false, resolve: true) @outputter.("Installing project modules\n\n") if resolve != false specs = Specs.new(specs, config) # If forcibly installing or if there is no Puppetfile, resolve # and write a Puppetfile. if force || !path.exist? @outputter.print_action_step("Resolving module dependencies, this might take a moment") # This doesn't use the block as it's more testable to just mock *_spin @outputter.start_spin puppetfile = Resolver.new.resolve(specs, config) @outputter.stop_spin # We get here either through 'bolt module install' which uses the # managed modulepath (which isn't configurable) or through bolt # project init --modules, which uses the default modulepath. This # should be safe to assume that if `.modules/` is the moduledir the # user is using the new workflow @outputter.print_action_step("Writing Puppetfile at #{path}") if moduledir.basename.to_s == '.modules' puppetfile.write(path, moduledir) else puppetfile.write(path) end # If not forcibly installing and there is a Puppetfile, assert # that it satisfies the specs. else puppetfile = Puppetfile.parse(path) puppetfile.assert_satisfies(specs) end end # Install the modules. install_puppetfile(path, moduledir, config) end |
#install_puppetfile(path, moduledir, config = {}) ⇒ Object
Installs the Puppetfile and generates types.
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/bolt/module_installer.rb', line 191 def install_puppetfile(path, moduledir, config = {}) @outputter.print_action_step("Syncing modules from #{path} to #{moduledir}") @outputter.start_spin ok = Installer.new(config).install(path, moduledir) @outputter.stop_spin # Automatically generate types after installing modules if ok @outputter.print_action_step("Generating type references") @pal.generate_types(cache: true) end @outputter.print_puppetfile_result(ok, path, moduledir) ok end |
#print_puppetfile_diff(old, new) ⇒ Object
Outputs a diff of an old Puppetfile and a new Puppetfile.
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/bolt/module_installer.rb', line 89 def print_puppetfile_diff(old, new) # Build hashes mapping the module name to the module object. This makes it # a little easier to determine which modules have been added, removed, or # modified. old = (old&.modules || []).each_with_object({}) do |mod, acc| next unless mod.type == :forge acc[mod.full_name] = mod end new = new.modules.each_with_object({}) do |mod, acc| next unless mod.type == :forge acc[mod.full_name] = mod end # New modules are those present in new but not in old. added = new.reject { |full_name, _mod| old.include?(full_name) }.values if added.any? diff = "Adding the following modules:\n" added.each { |mod| diff += "#{mod.full_name} #{mod.version}\n" } @outputter.print_action_step(diff) end # Upgraded modules are those that have a newer version in new than old. upgraded = new.select do |full_name, mod| if old.include?(full_name) mod.version > old[full_name].version end end.keys if upgraded.any? diff = "Upgrading the following modules:\n" upgraded.each { |full_name| diff += "#{full_name} #{old[full_name].version} to #{new[full_name].version}\n" } @outputter.print_action_step(diff) end # Downgraded modules are those that have an older version in new than old. downgraded = new.select do |full_name, mod| if old.include?(full_name) mod.version < old[full_name].version end end.keys if downgraded.any? diff = "Downgrading the following modules: \n" downgraded.each { |full_name| diff += "#{full_name} #{old[full_name].version} to #{new[full_name].version}\n" } @outputter.print_action_step(diff) end # Removed modules are those present in old but not in new. removed = old.reject { |full_name, _mod| new.include?(full_name) }.values if removed.any? diff = "Removing the following modules:\n" removed.each { |mod| diff += "#{mod.full_name} #{mod.version}\n" } @outputter.print_action_step(diff) end end |