Class: OpsWalrus::Bundler

Inherits:
Object
  • Object
show all
Includes:
Traversable
Defined in:
lib/opswalrus/bundler.rb

Constant Summary collapse

BUNDLE_DIR =
"opswalrus_bundle"

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Traversable

#pre_order_traverse

Constructor Details

#initialize(app, working_directory_path) ⇒ Bundler

Returns a new instance of Bundler.



17
18
19
20
21
# File 'lib/opswalrus/bundler.rb', line 17

def initialize(app, working_directory_path)
  @app = app
  @pwd = working_directory_path.to_pathname
  @bundle_dir = @pwd.join(BUNDLE_DIR)
end

Instance Attribute Details

#appObject

Returns the value of attribute app.



14
15
16
# File 'lib/opswalrus/bundler.rb', line 14

def app
  @app
end

#pwdObject

Returns the value of attribute pwd.



15
16
17
# File 'lib/opswalrus/bundler.rb', line 15

def pwd
  @pwd
end

Instance Method Details

#bundle_dirObject



23
24
25
# File 'lib/opswalrus/bundler.rb', line 23

def bundle_dir
  @bundle_dir
end

#delete_pwd_bundle_directoryObject



31
32
33
# File 'lib/opswalrus/bundler.rb', line 31

def delete_pwd_bundle_directory
  FileUtils.remove_dir(@bundle_dir) if @bundle_dir.exist?
end

#download_git_package(package_url, version = nil, destination_package_path = nil) ⇒ Object



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/opswalrus/bundler.rb', line 206

def download_git_package(package_url, version = nil, destination_package_path = nil)
  ensure_pwd_bundle_directory_exists

  destination_package_path ||= dynamic_package_path_for_git_package(package_url, version)

  App.instance.debug "Download git package #{package_url} version #{version.inspect} to #{destination_package_path}"

  return destination_package_path if destination_package_path.exist?

  if version
    ::Git.clone(package_url, destination_package_path, branch: version, config: ['submodule.recurse=true'])
  else
    ::Git.clone(package_url, destination_package_path, config: ['submodule.recurse=true'])
  end

  App.instance.debug "Downloaded git package #{package_url} version #{version.inspect} to #{destination_package_path}"

  destination_package_path
end

#download_import_dependencies(*ops_files, force: false) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/opswalrus/bundler.rb', line 92

def download_import_dependencies(*ops_files, force: false)
  ops_files.flatten.each do |ops_file|
    ops_file.imports.each do |local_name, import_reference|
      case import_reference
      when PackageDependencyReference, DynamicPackageImportReference
        package_reference = import_reference.package_reference
        download_package(ops_file.dirname, ops_file.ops_file_path, package_reference, force: force)
      when DirectoryReference
        # noop
      when OpsFileReference
        # noop
      end
    end
  end
end

#download_package(relative_base_path, source_of_package_reference, package_reference, force: false) ⇒ Object

This method downloads a package_url that is a dependency referenced in the specified package_file returns the destination directory that the package was downloaded to

relative_base_path is the relative base path that any relative file paths captured in the package_reference should be evaluated relative to



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/opswalrus/bundler.rb', line 141

def download_package(relative_base_path, source_of_package_reference, package_reference, force: false)
  ensure_pwd_bundle_directory_exists

  local_name = package_reference.local_name
  package_url = package_reference.package_uri
  version = package_reference.version

  destination_package_path = @bundle_dir.join(package_reference.import_resolution_dirname)

  # App.instance.log("Downloading #{package_reference} referenced in #{package_file.package_file_path} to #{destination_package_path}")
  App.instance.log("Downloading #{package_reference} referenced in #{source_of_package_reference} to #{destination_package_path}")

  # we return early here under the assumption that an already downloaded package/version combo will not
  # differ if we download it again multiple times to the same location
  if destination_package_path.exist? && !force
    App.instance.log("Skipping #{package_reference} referenced in #{source_of_package_reference} since it already has been downloaded to #{destination_package_path}")
    return destination_package_path
  end
  FileUtils.remove_dir(destination_package_path) if destination_package_path.exist?

  # download_package_contents(package_file.containing_directory, local_name, package_url, version, destination_package_path)
  download_package_contents(relative_base_path, local_name, package_url, version, destination_package_path)

  destination_package_path
end

#download_package_contents(relative_base_path, local_name, package_url, version, destination_package_path) ⇒ Object

relative_base_path is a Pathname



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/opswalrus/bundler.rb', line 168

def download_package_contents(relative_base_path, local_name, package_url, version, destination_package_path)
  package_path = package_url.to_pathname
  package_path = package_path.to_s.gsub(/^~/, Dir.home).to_pathname
  App.instance.trace("download_package_contents #{package_path}")
  if package_path.absolute? && package_path.exist?                                   # absolute path reference
    return case
    when package_path.directory?
      package_path_to_download = package_path.realpath
      App.instance.debug("Copying #{package_path_to_download} to #{destination_package_path}")
      FileUtils.cp_r(package_path_to_download, destination_package_path)
    when package_path.file?
      raise Error, "Package reference must be a directory, not a file:: #{local_name}: #{package_path}"
    else
      raise Error, "Unknown package reference for absolute path: #{local_name}: #{package_path}"
    end
  end
  if package_path.relative?                                                          # relative path reference
    rebased_path = relative_base_path.join(package_path)
    if rebased_path.exist?
      return case
      when rebased_path.directory?
        App.instance.debug("Copying #{package_path_to_download} to #{destination_package_path}")
        package_path_to_download = rebased_path.realpath
        FileUtils.cp_r(package_path_to_download, destination_package_path)
      when rebased_path.file?
        raise Error, "Package reference must be a directory, not a file:: #{local_name}: #{package_path}"
      else
        raise Error, "Unknown package reference for relative path: #{local_name}: #{package_path}"
      end
    end
  end

  if package_uri = Git.repo?(package_url)                                                          # git repo
    App.instance.debug("Cloning repo #{package_uri} into #{destination_package_path}")
    download_git_package(package_uri, version, destination_package_path)
  end
end

#download_package_dependencies(package_file, force: false) ⇒ Object

returns the array of the destination directories that the packages that ops_file depend on were downloaded to e.g. [dir_path1, dir_path2, dir_path3, …]



110
111
112
113
114
115
116
# File 'lib/opswalrus/bundler.rb', line 110

def download_package_dependencies(package_file, force: false)
  containing_directory = package_file.containing_directory
  package_file_source = package_file.package_file_path
  package_file.dependencies.map do |local_name, package_reference|
    download_package(containing_directory, package_file_source, package_reference, force: force)
  end
end

#download_package_dependency_tree(*ops_files_and_package_files, force: false) ⇒ Object

downloads all transitive package dependencies associated with ops_files_and_package_files all downloaded packages are placed into @bundle_dir



79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/opswalrus/bundler.rb', line 79

def download_package_dependency_tree(*ops_files_and_package_files, force: false)
  package_files = ops_files_and_package_files.flatten.map(&:package_file).compact.uniq

  package_files.each do |root_package_file|
    pre_order_traverse(root_package_file) do |package_file|
      download_package_dependencies(package_file, force: force).map do |downloaded_package_directory_path|
        package_file_path = File.join(downloaded_package_directory_path, "package.yaml")
        PackageFile.new(package_file_path)
      end
    end
  end
end

#dynamic_package_path_for_git_package(package_url, version = nil) ⇒ Object



226
227
228
229
# File 'lib/opswalrus/bundler.rb', line 226

def dynamic_package_path_for_git_package(package_url, version = nil)
  package_reference_dirname = DynamicPackageReference.import_resolution_dirname(package_url, version)
  bundle_dir.join(package_reference_dirname)
end

#ensure_pwd_bundle_directory_existsObject



27
28
29
# File 'lib/opswalrus/bundler.rb', line 27

def ensure_pwd_bundle_directory_exists
  FileUtils.mkdir_p(@bundle_dir) unless @bundle_dir.exist?
end

#unzip(zip_bundle_file, output_dir = nil) ⇒ Object

returns the directory that the zip file is unzipped into



232
233
234
235
236
237
238
239
# File 'lib/opswalrus/bundler.rb', line 232

def unzip(zip_bundle_file, output_dir = nil)
  if zip_bundle_file.to_pathname.exist?
    output_dir ||= Dir.mktmpdir.to_pathname

    # unzip the bundle into the output_dir directory
    DirZipper.unzip(zip_bundle_file, output_dir)
  end
end

#update(force = false) ⇒ Object

# we want to bundle the package represented by package_file into the bundle directory that # resides within the package directory that contains the package_file def build_bundle_for_package(package_file)

bundler_for_package = Bundler.new(package_file.dirname)
bundler_for_package.update
bundler_for_package.include_directory_in_bundle_as_self_pkg(pwd)

end



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/opswalrus/bundler.rb', line 58

def update(force = false)
  # delete_pwd_bundle_directory   # this was causing problems when we do: ops run -r -b ... because a dynamic package reference was being
                                  # downloaded to the bundle dir, and then update was being called afterward, which was blowing away
                                  # the entire bundle dir, so when the bundle dir was copied to the remote host, the ops file being
                                  # invoked was not present on the remote host, since it had never been copied over as a result
                                  # of the bundle dir being blown away after the dynamic package reference had been downloaded
  ensure_pwd_bundle_directory_exists

  package_yaml_files = pwd.glob("./**/package.yaml") - pwd.glob("./**/#{BUNDLE_DIR}/**/package.yaml")
  package_files_within_pwd = package_yaml_files.map {|path| PackageFile.new(path.realpath) }

  download_package_dependency_tree(package_files_within_pwd, force: force)

  ops_files = pwd.glob("./**/*.ops") - pwd.glob("./**/#{BUNDLE_DIR}/**/*.ops")
  ops_files_within_pwd = ops_files.map {|path| OpsFile.new(@app, path.realpath) }

  download_import_dependencies(ops_files_within_pwd, force: force)
end